11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project
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 */
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlurMaskFilter.h"
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlurMask.h"
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBuffer.h"
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMaskFilter.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkBlurMaskFilterImpl : public SkMaskFilter {
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle,
181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                         uint32_t flags);
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // overrides from SkMaskFilter
211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual SkMask::Format getFormat() SK_OVERRIDE;
221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            SkIPoint* margin) SK_OVERRIDE;
241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual BlurType asABlur(BlurInfo*) const SK_OVERRIDE;
251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual void computeFastBounds(const SkRect& src, SkRect* dst) SK_OVERRIDE;
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // overrides from SkFlattenable
281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual Factory getFactory() SK_OVERRIDE;
291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual void flatten(SkFlattenableWriteBuffer&) SK_OVERRIDE;
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate:
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar                    fRadius;
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkBlurMaskFilter::BlurStyle fBlurStyle;
3640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    uint32_t                    fBlurFlags;
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkBlurMaskFilterImpl(SkFlattenableReadBuffer&);
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    typedef SkMaskFilter INHERITED;
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
431cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius,
441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                       SkBlurMaskFilter::BlurStyle style,
451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                       uint32_t flags) {
461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // use !(radius > 0) instead of radius <= 0 to reject NaN values
471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!(radius > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount
481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        || flags > SkBlurMaskFilter::kAll_BlurFlag) {
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return NULL;
501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags));
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
571cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius,
581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           SkBlurMaskFilter::BlurStyle style,
5940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                           uint32_t flags)
601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    : fRadius(radius), fBlurStyle(style), fBlurFlags(flags) {
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 0
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fGamma = NULL;
631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (gammaScale) {
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fGamma = new U8[256];
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (gammaScale > 0)
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkBlurMask::BuildSqrGamma(fGamma, gammaScale);
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale);
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(radius >= 0);
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount);
7340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
761cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkMask::Format SkBlurMaskFilterImpl::getFormat() {
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkMask::kA8_Format;
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                      const SkMatrix& matrix, SkIPoint* margin) {
8240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkScalar radius;
831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
8440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        radius = fRadius;
851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
8640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        radius = matrix.mapRadius(fRadius);
871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
8840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
89af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // To avoid unseemly allocation requests (esp. for finite platforms like
90af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // handset) we limit the radius so something manageable. (as opposed to
91af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // a request like 10,000)
92af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    static const SkScalar MAX_RADIUS = SkIntToScalar(128);
93af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    radius = SkMinScalar(radius, MAX_RADIUS);
941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkBlurMask::Quality blurQuality =
951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality;
971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            blurQuality, margin);
100717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger}
101717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
102717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenbergervoid SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) {
103717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    dst->set(src.fLeft - fRadius, src.fTop - fRadius,
104717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger             src.fRight + fRadius, src.fBottom + fRadius);
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1071cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkFlattenable* SkBlurMaskFilterImpl::CreateProc(SkFlattenableReadBuffer& buffer) {
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkNEW_ARGS(SkBlurMaskFilterImpl, (buffer));
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1111cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkFlattenable::Factory SkBlurMaskFilterImpl::getFactory() {
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return CreateProc;
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1151cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer)
1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        : SkMaskFilter(buffer) {
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRadius = buffer.readScalar();
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readS32();
11940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    fBlurFlags = buffer.readU32() & SkBlurMaskFilter::kAll_BlurFlag;
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(fRadius >= 0);
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) {
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->INHERITED::flatten(buffer);
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.writeScalar(fRadius);
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.write32(fBlurStyle);
12840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    buffer.write32(fBlurFlags);
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic const SkMaskFilter::BlurType gBlurStyle2BlurType[] = {
1321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMaskFilter::kNormal_BlurType,
1331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMaskFilter::kSolid_BlurType,
1341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMaskFilter::kOuter_BlurType,
1351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMaskFilter::kInner_BlurType,
1361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger};
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1381cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkMaskFilter::BlurType SkBlurMaskFilterImpl::asABlur(BlurInfo* info) const {
1391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (info) {
1401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        info->fRadius = fRadius;
1411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag);
1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag);
1431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return gBlurStyle2BlurType[fBlurStyle];
1451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1471cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
1481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
1491cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
150