SkBlurDrawLooper.cpp revision 336b4da6b0d20f27f9980b03415354a2f0698e18
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        blurFlags |= flags & kCoarseRadius_BlurFlag ?
31            SkBlurMaskFilter::kCoarseRadius_BlurFlag :
32            SkBlurMaskFilter::kNone_BlurFlag;
33
34        fBlur = SkBlurMaskFilter::Create(radius,
35                                         SkBlurMaskFilter::kNormal_BlurStyle,
36                                         blurFlags);
37    } else {
38        fBlur = NULL;
39    }
40
41    if (flags & kOverrideColor_BlurFlag) {
42        // Set alpha to 1 for the override since transparency will already
43        // be baked into the blurred mask.
44        SkColor opaqueColor = SkColorSetA(color, 255);
45        //The SrcIn xfer mode will multiply 'color' by the incoming alpha
46        fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
47                                                       SkXfermode::kSrcIn_Mode);
48    } else {
49        fColorFilter = NULL;
50    }
51}
52
53SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
54: INHERITED(buffer) {
55
56    fDx = buffer.readScalar();
57    fDy = buffer.readScalar();
58    fBlurColor = buffer.readColor();
59    fBlur = buffer.readFlattenableT<SkMaskFilter>();
60    fColorFilter = buffer.readFlattenableT<SkColorFilter>();
61    fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
62}
63
64SkBlurDrawLooper::~SkBlurDrawLooper() {
65    SkSafeUnref(fBlur);
66    SkSafeUnref(fColorFilter);
67}
68
69void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
70    this->INHERITED::flatten(buffer);
71    buffer.writeScalar(fDx);
72    buffer.writeScalar(fDy);
73    buffer.writeColor(fBlurColor);
74    buffer.writeFlattenable(fBlur);
75    buffer.writeFlattenable(fColorFilter);
76    buffer.writeUInt(fBlurFlags);
77}
78
79void SkBlurDrawLooper::init(SkCanvas* canvas) {
80    fState = kBeforeEdge;
81}
82
83bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
84    switch (fState) {
85        case kBeforeEdge:
86            // we do nothing if a maskfilter is already installed
87            if (paint->getMaskFilter()) {
88                fState = kDone;
89                return false;
90            }
91#ifdef SK_BUILD_FOR_ANDROID
92            SkColor blurColor;
93            blurColor = fBlurColor;
94            if (SkColorGetA(blurColor) == 255) {
95                blurColor = SkColorSetA(blurColor, paint->getAlpha());
96            }
97            paint->setColor(blurColor);
98#else
99            paint->setColor(fBlurColor);
100#endif
101            paint->setMaskFilter(fBlur);
102            paint->setColorFilter(fColorFilter);
103            canvas->save(SkCanvas::kMatrix_SaveFlag);
104            if (fBlurFlags & kIgnoreTransform_BlurFlag) {
105                SkMatrix transform(canvas->getTotalMatrix());
106                transform.postTranslate(fDx, fDy);
107                canvas->setMatrix(transform);
108            } else {
109                canvas->translate(fDx, fDy);
110            }
111            fState = kAfterEdge;
112            return true;
113        case kAfterEdge:
114            canvas->restore();
115            fState = kDone;
116            return true;
117        default:
118            SkASSERT(kDone == fState);
119            return false;
120    }
121}
122