blob: eb64000007523e9442af824071ded204d0a472c3 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include "SkBlurMaskFilter.h"
11#include "SkBlurMask.h"
12#include "SkBuffer.h"
13#include "SkMaskFilter.h"
14
15class SkBlurMaskFilterImpl : public SkMaskFilter {
16public:
reed@google.com03016a32011-08-12 14:59:59 +000017 SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle,
18 uint32_t flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +000019
20 // overrides from SkMaskFilter
bungeman@google.com18ac1ba2011-10-04 15:11:38 +000021 virtual SkMask::Format getFormat() SK_OVERRIDE;
reed@google.com03016a32011-08-12 14:59:59 +000022 virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
bungeman@google.com18ac1ba2011-10-04 15:11:38 +000023 SkIPoint* margin) SK_OVERRIDE;
24 virtual BlurType asABlur(BlurInfo*) const SK_OVERRIDE;
djsollen@google.come63793a2012-03-21 15:39:03 +000025 virtual void computeFastBounds(const SkRect& src, SkRect* dst) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +000026
27 // overrides from SkFlattenable
bungeman@google.com18ac1ba2011-10-04 15:11:38 +000028 virtual void flatten(SkFlattenableWriteBuffer&) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +000029
djsollen@google.comba28d032012-03-26 17:57:35 +000030 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl)
reed@android.com8a1c16f2008-12-17 15:59:43 +000031
32private:
33 SkScalar fRadius;
34 SkBlurMaskFilter::BlurStyle fBlurStyle;
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000035 uint32_t fBlurFlags;
reed@android.com8a1c16f2008-12-17 15:59:43 +000036
37 SkBlurMaskFilterImpl(SkFlattenableReadBuffer&);
38
39 typedef SkMaskFilter INHERITED;
40};
41
reed@google.com03016a32011-08-12 14:59:59 +000042SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius,
43 SkBlurMaskFilter::BlurStyle style,
44 uint32_t flags) {
reed@google.come5828692012-01-11 14:07:27 +000045 // use !(radius > 0) instead of radius <= 0 to reject NaN values
46 if (!(radius > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount
reed@google.com03016a32011-08-12 14:59:59 +000047 || flags > SkBlurMaskFilter::kAll_BlurFlag) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000048 return NULL;
reed@google.com03016a32011-08-12 14:59:59 +000049 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000050
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000051 return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags));
reed@android.com8a1c16f2008-12-17 15:59:43 +000052}
53
reed@google.com03016a32011-08-12 14:59:59 +000054///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +000055
reed@google.com03016a32011-08-12 14:59:59 +000056SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius,
57 SkBlurMaskFilter::BlurStyle style,
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000058 uint32_t flags)
reed@google.com03016a32011-08-12 14:59:59 +000059 : fRadius(radius), fBlurStyle(style), fBlurFlags(flags) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000060#if 0
61 fGamma = NULL;
reed@google.com03016a32011-08-12 14:59:59 +000062 if (gammaScale) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000063 fGamma = new U8[256];
64 if (gammaScale > 0)
65 SkBlurMask::BuildSqrGamma(fGamma, gammaScale);
66 else
67 SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale);
68 }
69#endif
70 SkASSERT(radius >= 0);
71 SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount);
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000072 SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
reed@android.com8a1c16f2008-12-17 15:59:43 +000073}
74
reed@google.com03016a32011-08-12 14:59:59 +000075SkMask::Format SkBlurMaskFilterImpl::getFormat() {
reed@android.com8a1c16f2008-12-17 15:59:43 +000076 return SkMask::kA8_Format;
77}
78
reed@google.com03016a32011-08-12 14:59:59 +000079bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
80 const SkMatrix& matrix, SkIPoint* margin) {
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000081 SkScalar radius;
reed@google.com03016a32011-08-12 14:59:59 +000082 if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000083 radius = fRadius;
reed@google.com03016a32011-08-12 14:59:59 +000084 } else {
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000085 radius = matrix.mapRadius(fRadius);
reed@google.com03016a32011-08-12 14:59:59 +000086 }
senorblanco@chromium.org038aff62010-12-06 23:45:58 +000087
reed@android.com35555912009-03-16 18:46:55 +000088 // To avoid unseemly allocation requests (esp. for finite platforms like
89 // handset) we limit the radius so something manageable. (as opposed to
90 // a request like 10,000)
91 static const SkScalar MAX_RADIUS = SkIntToScalar(128);
92 radius = SkMinScalar(radius, MAX_RADIUS);
reed@google.com03016a32011-08-12 14:59:59 +000093 SkBlurMask::Quality blurQuality =
94 (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
95 SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality;
reed@android.com8a1c16f2008-12-17 15:59:43 +000096
bungeman@google.com5af16f82011-09-02 15:06:44 +000097 return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
98 blurQuality, margin);
reed@android.com8a1c16f2008-12-17 15:59:43 +000099}
100
reed@google.com9efd9a02012-01-30 15:41:43 +0000101void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) {
102 dst->set(src.fLeft - fRadius, src.fTop - fRadius,
103 src.fRight + fRadius, src.fBottom + fRadius);
104}
105
reed@google.com03016a32011-08-12 14:59:59 +0000106SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer)
107 : SkMaskFilter(buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000108 fRadius = buffer.readScalar();
109 fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readS32();
senorblanco@chromium.org038aff62010-12-06 23:45:58 +0000110 fBlurFlags = buffer.readU32() & SkBlurMaskFilter::kAll_BlurFlag;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000111 SkASSERT(fRadius >= 0);
112 SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
113}
114
reed@google.com03016a32011-08-12 14:59:59 +0000115void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116 this->INHERITED::flatten(buffer);
117 buffer.writeScalar(fRadius);
118 buffer.write32(fBlurStyle);
senorblanco@chromium.org038aff62010-12-06 23:45:58 +0000119 buffer.write32(fBlurFlags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120}
121
reed@google.com2b75f422011-07-07 13:43:38 +0000122static const SkMaskFilter::BlurType gBlurStyle2BlurType[] = {
123 SkMaskFilter::kNormal_BlurType,
124 SkMaskFilter::kSolid_BlurType,
125 SkMaskFilter::kOuter_BlurType,
126 SkMaskFilter::kInner_BlurType,
127};
128
bungeman@google.com18ac1ba2011-10-04 15:11:38 +0000129SkMaskFilter::BlurType SkBlurMaskFilterImpl::asABlur(BlurInfo* info) const {
reed@google.com2b75f422011-07-07 13:43:38 +0000130 if (info) {
131 info->fRadius = fRadius;
132 info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag);
133 info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag);
134 }
135 return gBlurStyle2BlurType[fBlurStyle];
136}
137
caryclark@google.comd26147a2011-12-15 14:16:43 +0000138SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
139 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
140SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END