10910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* libs/graphics/effects/SkBlurMaskFilter.cpp
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
30910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** Copyright 2006, The Android Open Source Project
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
50910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
60910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** you may not use this file except in compliance with the License.
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** You may obtain a copy of the License at
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** See the License for the specific language governing permissions and
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** limitations under the License.
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlurMaskFilter.h"
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlurMask.h"
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBuffer.h"
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMaskFilter.h"
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkBlurMaskFilterImpl : public SkMaskFilter {
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
2540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle style, uint32_t flags);
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // overrides from SkMaskFilter
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual SkMask::Format getFormat();
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix& matrix, SkIPoint* margin);
30717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    virtual void computeFastBounds(const SkRect& src, SkRect* dst);
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // overrides from SkFlattenable
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // This method is not exported to java.
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual Factory getFactory();
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // This method is not exported to java.
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void flatten(SkFlattenableWriteBuffer&);
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate:
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar                    fRadius;
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkBlurMaskFilter::BlurStyle fBlurStyle;
4340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    uint32_t                    fBlurFlags;
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkBlurMaskFilterImpl(SkFlattenableReadBuffer&);
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    typedef SkMaskFilter INHERITED;
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius, SkBlurMaskFilter::BlurStyle style,
5140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                       uint32_t flags)
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (radius <= 0 || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount
5440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        || flags > SkBlurMaskFilter::kAll_BlurFlag)
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return NULL;
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags));
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////////////////////////////////
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle style,
6340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                           uint32_t flags)
6440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    : fRadius(radius), fBlurStyle(style), fBlurFlags(flags)
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 0
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fGamma = NULL;
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (gammaScale)
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fGamma = new U8[256];
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (gammaScale > 0)
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkBlurMask::BuildSqrGamma(fGamma, gammaScale);
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale);
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(radius >= 0);
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount);
7940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkMask::Format SkBlurMaskFilterImpl::getFormat()
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkMask::kA8_Format;
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, const SkMatrix& matrix, SkIPoint* margin)
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
8940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkScalar radius;
9040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag)
9140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        radius = fRadius;
9240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    else
9340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        radius = matrix.mapRadius(fRadius);
9440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
95af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // To avoid unseemly allocation requests (esp. for finite platforms like
96af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // handset) we limit the radius so something manageable. (as opposed to
97af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // a request like 10,000)
98af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    static const SkScalar MAX_RADIUS = SkIntToScalar(128);
99af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    radius = SkMinScalar(radius, MAX_RADIUS);
10071531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    SkBlurMask::Quality blurQuality = (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
10171531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality;
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10371531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger    if (SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle, blurQuality))
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
105af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (margin) {
106af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            // we need to integralize radius for our margin, so take the ceil
107af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            // just to be safe.
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            margin->set(SkScalarCeil(radius), SkScalarCeil(radius));
109af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        }
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return false;
113717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger}
114717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
115717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenbergervoid SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) {
116717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    dst->set(src.fLeft - fRadius, src.fTop - fRadius,
117717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger             src.fRight + fRadius, src.fBottom + fRadius);
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkFlattenable* SkBlurMaskFilterImpl::CreateProc(SkFlattenableReadBuffer& buffer)
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkNEW_ARGS(SkBlurMaskFilterImpl, (buffer));
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkFlattenable::Factory SkBlurMaskFilterImpl::getFactory()
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return CreateProc;
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer) : SkMaskFilter(buffer)
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRadius = buffer.readScalar();
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readS32();
13440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    fBlurFlags = buffer.readU32() & SkBlurMaskFilter::kAll_BlurFlag;
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(fRadius >= 0);
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer)
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->INHERITED::flatten(buffer);
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.writeScalar(fRadius);
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.write32(fBlurStyle);
14440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    buffer.write32(fBlurFlags);
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkFlattenable::Registrar gReg("SkBlurMaskFilter",
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                     SkBlurMaskFilterImpl::CreateProc);
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
152