1/* libs/graphics/effects/SkBlurMaskFilter.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkBlurMaskFilter.h"
19#include "SkBlurMask.h"
20#include "SkBuffer.h"
21#include "SkMaskFilter.h"
22
23class SkBlurMaskFilterImpl : public SkMaskFilter {
24public:
25    SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle style);
26
27    // overrides from SkMaskFilter
28    virtual SkMask::Format getFormat();
29    virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix& matrix, SkIPoint* margin);
30
31    // overrides from SkFlattenable
32    // This method is not exported to java.
33    virtual Factory getFactory();
34    // This method is not exported to java.
35    virtual void flatten(SkFlattenableWriteBuffer&);
36
37    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
38
39private:
40    SkScalar                    fRadius;
41    SkBlurMaskFilter::BlurStyle fBlurStyle;
42
43    SkBlurMaskFilterImpl(SkFlattenableReadBuffer&);
44
45    typedef SkMaskFilter INHERITED;
46};
47
48SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius, SkBlurMaskFilter::BlurStyle style)
49{
50    if (radius <= 0 || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount)
51        return NULL;
52
53    return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style));
54}
55
56/////////////////////////////////////////////////////////////////////////////////////////////////////////
57
58SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle style)
59    : fRadius(radius), fBlurStyle(style)
60{
61#if 0
62    fGamma = NULL;
63    if (gammaScale)
64    {
65        fGamma = new U8[256];
66        if (gammaScale > 0)
67            SkBlurMask::BuildSqrGamma(fGamma, gammaScale);
68        else
69            SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale);
70    }
71#endif
72    SkASSERT(radius >= 0);
73    SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount);
74}
75
76SkMask::Format SkBlurMaskFilterImpl::getFormat()
77{
78    return SkMask::kA8_Format;
79}
80
81bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, const SkMatrix& matrix, SkIPoint* margin)
82{
83    SkScalar radius = matrix.mapRadius(fRadius);
84    // To avoid unseemly allocation requests (esp. for finite platforms like
85    // handset) we limit the radius so something manageable. (as opposed to
86    // a request like 10,000)
87    static const SkScalar MAX_RADIUS = SkIntToScalar(128);
88    radius = SkMinScalar(radius, MAX_RADIUS);
89
90    if (SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle))
91    {
92        if (margin) {
93            // we need to integralize radius for our margin, so take the ceil
94            // just to be safe.
95            margin->set(SkScalarCeil(radius), SkScalarCeil(radius));
96        }
97        return true;
98    }
99    return false;
100}
101
102SkFlattenable* SkBlurMaskFilterImpl::CreateProc(SkFlattenableReadBuffer& buffer)
103{
104    return SkNEW_ARGS(SkBlurMaskFilterImpl, (buffer));
105}
106
107SkFlattenable::Factory SkBlurMaskFilterImpl::getFactory()
108{
109    return CreateProc;
110}
111
112SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer) : SkMaskFilter(buffer)
113{
114    fRadius = buffer.readScalar();
115    fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readS32();
116    SkASSERT(fRadius >= 0);
117    SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
118}
119
120void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer)
121{
122    this->INHERITED::flatten(buffer);
123    buffer.writeScalar(fRadius);
124    buffer.write32(fBlurStyle);
125}
126
127///////////////////////////////////////////////////////////////////////////////
128
129static SkFlattenable::Registrar gReg("SkBlurMaskFilter",
130                                     SkBlurMaskFilterImpl::CreateProc);
131
132