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