Home | History | Annotate | Download | only in effects
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      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 
      9 
     10 #include "SkBlurMaskFilter.h"
     11 #include "SkBlurMask.h"
     12 #include "SkBuffer.h"
     13 #include "SkMaskFilter.h"
     14 
     15 class SkBlurMaskFilterImpl : public SkMaskFilter {
     16 public:
     17     SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle,
     18                          uint32_t flags);
     19 
     20     // overrides from SkMaskFilter
     21     virtual SkMask::Format getFormat() SK_OVERRIDE;
     22     virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
     23                             SkIPoint* margin) SK_OVERRIDE;
     24     virtual BlurType asABlur(BlurInfo*) const SK_OVERRIDE;
     25     virtual void computeFastBounds(const SkRect& src, SkRect* dst) SK_OVERRIDE;
     26 
     27     // overrides from SkFlattenable
     28     virtual Factory getFactory() SK_OVERRIDE;
     29     virtual void flatten(SkFlattenableWriteBuffer&) SK_OVERRIDE;
     30 
     31     static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
     32 
     33 private:
     34     SkScalar                    fRadius;
     35     SkBlurMaskFilter::BlurStyle fBlurStyle;
     36     uint32_t                    fBlurFlags;
     37 
     38     SkBlurMaskFilterImpl(SkFlattenableReadBuffer&);
     39 
     40     typedef SkMaskFilter INHERITED;
     41 };
     42 
     43 SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius,
     44                                        SkBlurMaskFilter::BlurStyle style,
     45                                        uint32_t flags) {
     46     // use !(radius > 0) instead of radius <= 0 to reject NaN values
     47     if (!(radius > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount
     48         || flags > SkBlurMaskFilter::kAll_BlurFlag) {
     49         return NULL;
     50     }
     51 
     52     return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags));
     53 }
     54 
     55 ///////////////////////////////////////////////////////////////////////////////
     56 
     57 SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius,
     58                                            SkBlurMaskFilter::BlurStyle style,
     59                                            uint32_t flags)
     60     : fRadius(radius), fBlurStyle(style), fBlurFlags(flags) {
     61 #if 0
     62     fGamma = NULL;
     63     if (gammaScale) {
     64         fGamma = new U8[256];
     65         if (gammaScale > 0)
     66             SkBlurMask::BuildSqrGamma(fGamma, gammaScale);
     67         else
     68             SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale);
     69     }
     70 #endif
     71     SkASSERT(radius >= 0);
     72     SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount);
     73     SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
     74 }
     75 
     76 SkMask::Format SkBlurMaskFilterImpl::getFormat() {
     77     return SkMask::kA8_Format;
     78 }
     79 
     80 bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
     81                                       const SkMatrix& matrix, SkIPoint* margin) {
     82     SkScalar radius;
     83     if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
     84         radius = fRadius;
     85     } else {
     86         radius = matrix.mapRadius(fRadius);
     87     }
     88 
     89     // To avoid unseemly allocation requests (esp. for finite platforms like
     90     // handset) we limit the radius so something manageable. (as opposed to
     91     // a request like 10,000)
     92     static const SkScalar MAX_RADIUS = SkIntToScalar(128);
     93     radius = SkMinScalar(radius, MAX_RADIUS);
     94     SkBlurMask::Quality blurQuality =
     95         (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
     96             SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality;
     97 
     98     return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
     99                             blurQuality, margin);
    100 }
    101 
    102 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) {
    103     dst->set(src.fLeft - fRadius, src.fTop - fRadius,
    104              src.fRight + fRadius, src.fBottom + fRadius);
    105 }
    106 
    107 SkFlattenable* SkBlurMaskFilterImpl::CreateProc(SkFlattenableReadBuffer& buffer) {
    108     return SkNEW_ARGS(SkBlurMaskFilterImpl, (buffer));
    109 }
    110 
    111 SkFlattenable::Factory SkBlurMaskFilterImpl::getFactory() {
    112     return CreateProc;
    113 }
    114 
    115 SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer)
    116         : SkMaskFilter(buffer) {
    117     fRadius = buffer.readScalar();
    118     fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readS32();
    119     fBlurFlags = buffer.readU32() & SkBlurMaskFilter::kAll_BlurFlag;
    120     SkASSERT(fRadius >= 0);
    121     SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
    122 }
    123 
    124 void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) {
    125     this->INHERITED::flatten(buffer);
    126     buffer.writeScalar(fRadius);
    127     buffer.write32(fBlurStyle);
    128     buffer.write32(fBlurFlags);
    129 }
    130 
    131 static const SkMaskFilter::BlurType gBlurStyle2BlurType[] = {
    132     SkMaskFilter::kNormal_BlurType,
    133     SkMaskFilter::kSolid_BlurType,
    134     SkMaskFilter::kOuter_BlurType,
    135     SkMaskFilter::kInner_BlurType,
    136 };
    137 
    138 SkMaskFilter::BlurType SkBlurMaskFilterImpl::asABlur(BlurInfo* info) const {
    139     if (info) {
    140         info->fRadius = fRadius;
    141         info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag);
    142         info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag);
    143     }
    144     return gBlurStyle2BlurType[fBlurStyle];
    145 }
    146 
    147 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
    148     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
    149 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
    150