SkBlurDrawLooper.cpp revision a0c2bc24381fea063008f9c8823756eb020603b3
1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "SkBlurDrawLooper.h"
9#include "SkBlurMaskFilter.h"
10#include "SkCanvas.h"
11#include "SkFlattenableBuffers.h"
12#include "SkPaint.h"
13#include "SkMaskFilter.h"
14#include "SkColorFilter.h"
15
16SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
17                                   SkColor color, uint32_t flags)
18    : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags), fState(kDone) {
19
20    SkASSERT(flags <= kAll_BlurFlag);
21    if (radius > 0) {
22        uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
23            SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
24            SkBlurMaskFilter::kNone_BlurFlag;
25
26        blurFlags |= flags & kHighQuality_BlurFlag ?
27            SkBlurMaskFilter::kHighQuality_BlurFlag :
28            SkBlurMaskFilter::kNone_BlurFlag;
29
30        fBlur = SkBlurMaskFilter::Create(radius,
31                                         SkBlurMaskFilter::kNormal_BlurStyle,
32                                         blurFlags);
33    } else {
34        fBlur = NULL;
35    }
36
37    if (flags & kOverrideColor_BlurFlag) {
38        // Set alpha to 1 for the override since transparency will already
39        // be baked into the blurred mask.
40        SkColor opaqueColor = SkColorSetA(color, 255);
41        //The SrcIn xfer mode will multiply 'color' by the incoming alpha
42        fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
43                                                       SkXfermode::kSrcIn_Mode);
44    } else {
45        fColorFilter = NULL;
46    }
47}
48
49SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
50: INHERITED(buffer) {
51
52    fDx = buffer.readScalar();
53    fDy = buffer.readScalar();
54    fBlurColor = buffer.readColor();
55    fBlur = buffer.readFlattenableT<SkMaskFilter>();
56    fColorFilter = buffer.readFlattenableT<SkColorFilter>();
57    fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
58}
59
60SkBlurDrawLooper::~SkBlurDrawLooper() {
61    SkSafeUnref(fBlur);
62    SkSafeUnref(fColorFilter);
63}
64
65void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
66    this->INHERITED::flatten(buffer);
67    buffer.writeScalar(fDx);
68    buffer.writeScalar(fDy);
69    buffer.writeColor(fBlurColor);
70    buffer.writeFlattenable(fBlur);
71    buffer.writeFlattenable(fColorFilter);
72    buffer.writeUInt(fBlurFlags);
73}
74
75void SkBlurDrawLooper::init(SkCanvas* canvas) {
76    fState = kBeforeEdge;
77}
78
79bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
80    switch (fState) {
81        case kBeforeEdge:
82            // we do nothing if a maskfilter is already installed
83            if (paint->getMaskFilter()) {
84                fState = kDone;
85                return false;
86            }
87#ifdef SK_BUILD_FOR_ANDROID
88            SkColor blurColor;
89            blurColor = fBlurColor;
90            if (SkColorGetA(blurColor) == 255) {
91                blurColor = SkColorSetA(blurColor, paint->getAlpha());
92            }
93            paint->setColor(blurColor);
94#else
95            paint->setColor(fBlurColor);
96#endif
97            paint->setMaskFilter(fBlur);
98            paint->setColorFilter(fColorFilter);
99            canvas->save(SkCanvas::kMatrix_SaveFlag);
100            if (fBlurFlags & kIgnoreTransform_BlurFlag) {
101                SkMatrix transform(canvas->getTotalMatrix());
102                transform.postTranslate(fDx, fDy);
103                canvas->setMatrix(transform);
104            } else {
105                canvas->translate(fDx, fDy);
106            }
107            fState = kAfterEdge;
108            return true;
109        case kAfterEdge:
110            canvas->restore();
111            fState = kDone;
112            return true;
113        default:
114            SkASSERT(kDone == fState);
115            return false;
116    }
117}
118