11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlurDrawLooper.h"
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlurMaskFilter.h"
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkCanvas.h"
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPaint.h"
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMaskFilter.h"
1371531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger#include "SkColorFilter.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
1640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                   SkColor color, uint32_t flags)
1787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags) {
1887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
1940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(flags <= kAll_BlurFlag);
2087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    if (radius > 0) {
2140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
2240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
2340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkBlurMaskFilter::kNone_BlurFlag;
2440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
2571531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        blurFlags |= flags & kHighQuality_BlurFlag ?
2671531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger            SkBlurMaskFilter::kHighQuality_BlurFlag :
2771531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger            SkBlurMaskFilter::kNone_BlurFlag;
2871531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fBlur = SkBlurMaskFilter::Create(radius,
3071531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger                                         SkBlurMaskFilter::kNormal_BlurStyle,
3140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                         blurFlags);
3287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fBlur = NULL;
3471531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    }
3571531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger
3687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    if (flags & kOverrideColor_BlurFlag) {
37137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger        // Set alpha to 1 for the override since transparency will already
38137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger        // be baked into the blurred mask.
39137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger        SkColor opaqueColor = SkColorSetA(color, 255);
4071531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        //The SrcIn xfer mode will multiply 'color' by the incoming alpha
4187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
4287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                                                       SkXfermode::kSrcIn_Mode);
4387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
4471531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        fColorFilter = NULL;
4571531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    }
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
481cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger: INHERITED(buffer) {
501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fDx = buffer.readScalar();
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fDy = buffer.readScalar();
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBlurColor = buffer.readU32();
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBlur = static_cast<SkMaskFilter*>(buffer.readFlattenable());
5571531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    fColorFilter = static_cast<SkColorFilter*>(buffer.readFlattenable());
5640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    fBlurFlags = buffer.readU32() & kAll_BlurFlag;
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5987b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkBlurDrawLooper::~SkBlurDrawLooper() {
6040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fBlur);
6171531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    SkSafeUnref(fColorFilter);
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) {
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.writeScalar(fDx);
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.writeScalar(fDy);
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.write32(fBlurColor);
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.writeFlattenable(fBlur);
6971531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    buffer.writeFlattenable(fColorFilter);
7040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    buffer.write32(fBlurFlags);
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkBlurDrawLooper::init(SkCanvas* canvas) {
7487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    fState = kBeforeEdge;
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergerbool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (fState) {
7987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        case kBeforeEdge:
8087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            // we do nothing if a maskfilter is already installed
8187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            if (paint->getMaskFilter()) {
8287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                fState = kDone;
8387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                return false;
8487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            }
851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
8687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            SkColor blurColor;
8787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            blurColor = fBlurColor;
8887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            if (SkColorGetA(blurColor) == 255) {
8987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                blurColor = SkColorSetA(blurColor, paint->getAlpha());
9087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            }
9187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            paint->setColor(blurColor);
9287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#else
9387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            paint->setColor(fBlurColor);
9487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
9587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            paint->setMaskFilter(fBlur);
9687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            paint->setColorFilter(fColorFilter);
9787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            canvas->save(SkCanvas::kMatrix_SaveFlag);
9887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            if (fBlurFlags & kIgnoreTransform_BlurFlag) {
9987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                SkMatrix transform(canvas->getTotalMatrix());
10087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                transform.postTranslate(fDx, fDy);
10187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                canvas->setMatrix(transform);
10287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            } else {
10387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                canvas->translate(fDx, fDy);
10487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            }
10587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            fState = kAfterEdge;
10687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            return true;
10787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        case kAfterEdge:
10887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            canvas->restore();
10987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            fState = kDone;
11087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            return true;
11187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        default:
11287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            SkASSERT(kDone == fState);
11387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            return false;
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1191cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSK_DEFINE_FLATTENABLE_REGISTRAR(SkBlurDrawLooper)
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
121