OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkBlurMaskFilter.h" | 9 #include "SkBlurMaskFilter.h" |
10 #include "SkBlurMask.h" | 10 #include "SkBlurMask.h" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 const SkIRect& clipBounds, | 53 const SkIRect& clipBounds, |
54 NinePatch*) const SK_OVERRIDE; | 54 NinePatch*) const SK_OVERRIDE; |
55 | 55 |
56 bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix, | 56 bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix, |
57 SkIPoint* margin, SkMask::CreateMode createMode) const; | 57 SkIPoint* margin, SkMask::CreateMode createMode) const; |
58 | 58 |
59 private: | 59 private: |
60 // To avoid unseemly allocation requests (esp. for finite platforms like | 60 // To avoid unseemly allocation requests (esp. for finite platforms like |
61 // handset) we limit the radius so something manageable. (as opposed to | 61 // handset) we limit the radius so something manageable. (as opposed to |
62 // a request like 10,000) | 62 // a request like 10,000) |
63 static const SkScalar kMAX_RADIUS; | 63 static const SkScalar kMAX_BLUR_RADIUS; |
64 // This constant approximates the scaling done in the software path's | 64 // This constant approximates the scaling done in the software path's |
65 // "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)). | 65 // "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)). |
66 // IMHO, it actually should be 1: we blur "less" than we should do | 66 // IMHO, it actually should be 1: we blur "less" than we should do |
67 // according to the CSS and canvas specs, simply because Safari does the sam
e. | 67 // according to the CSS and canvas specs, simply because Safari does the sam
e. |
68 // Firefox used to do the same too, until 4.0 where they fixed it. So at so
me | 68 // Firefox used to do the same too, until 4.0 where they fixed it. So at so
me |
69 // point we should probably get rid of these scaling constants and rebaselin
e | 69 // point we should probably get rid of these scaling constants and rebaselin
e |
70 // all the blur tests. | 70 // all the blur tests. |
71 static const SkScalar kBLUR_SIGMA_SCALE; | 71 static const SkScalar kBLUR_SIGMA_SCALE; |
72 | 72 |
73 SkScalar fRadius; | 73 SkScalar fRadius; |
74 SkBlurMaskFilter::BlurStyle fBlurStyle; | 74 SkBlurMaskFilter::BlurStyle fBlurStyle; |
75 uint32_t fBlurFlags; | 75 uint32_t fBlurFlags; |
76 | 76 |
77 SkBlurMaskFilterImpl(SkFlattenableReadBuffer&); | 77 SkBlurMaskFilterImpl(SkFlattenableReadBuffer&); |
78 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; | 78 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; |
79 #if SK_SUPPORT_GPU | 79 #if SK_SUPPORT_GPU |
80 SkScalar computeXformedRadius(const SkMatrix& ctm) const { | 80 SkScalar computeXformedRadius(const SkMatrix& ctm) const { |
81 bool ignoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTr
ansform_BlurFlag); | 81 bool ignoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTr
ansform_BlurFlag); |
82 | 82 |
83 SkScalar xformedRadius = ignoreTransform ? fRadius | 83 SkScalar xformedRadius = ignoreTransform ? fRadius |
84 : ctm.mapRadius(fRadius); | 84 : ctm.mapRadius(fRadius); |
85 return SkMinScalar(xformedRadius, kMAX_RADIUS); | 85 return SkMinScalar(xformedRadius, kMAX_BLUR_RADIUS); |
86 } | 86 } |
87 #endif | 87 #endif |
88 | 88 |
89 typedef SkMaskFilter INHERITED; | 89 typedef SkMaskFilter INHERITED; |
90 }; | 90 }; |
91 | 91 |
92 const SkScalar SkBlurMaskFilterImpl::kMAX_RADIUS = SkIntToScalar(128); | 92 const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_RADIUS = SkIntToScalar(128); |
93 const SkScalar SkBlurMaskFilterImpl::kBLUR_SIGMA_SCALE = 0.6f; | 93 const SkScalar SkBlurMaskFilterImpl::kBLUR_SIGMA_SCALE = SkFloatToScalar(0.6f); |
94 | 94 |
95 SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius, | 95 SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius, |
96 SkBlurMaskFilter::BlurStyle style, | 96 SkBlurMaskFilter::BlurStyle style, |
97 uint32_t flags) { | 97 uint32_t flags) { |
98 // use !(radius > 0) instead of radius <= 0 to reject NaN values | 98 // use !(radius > 0) instead of radius <= 0 to reject NaN values |
99 if (!(radius > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount | 99 if (!(radius > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount |
100 || flags > SkBlurMaskFilter::kAll_BlurFlag) { | 100 || flags > SkBlurMaskFilter::kAll_BlurFlag) { |
101 return NULL; | 101 return NULL; |
102 } | 102 } |
103 | 103 |
(...skipping 28 matching lines...) Expand all Loading... |
132 bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, | 132 bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, |
133 const SkMatrix& matrix, | 133 const SkMatrix& matrix, |
134 SkIPoint* margin) const{ | 134 SkIPoint* margin) const{ |
135 SkScalar radius; | 135 SkScalar radius; |
136 if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { | 136 if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { |
137 radius = fRadius; | 137 radius = fRadius; |
138 } else { | 138 } else { |
139 radius = matrix.mapRadius(fRadius); | 139 radius = matrix.mapRadius(fRadius); |
140 } | 140 } |
141 | 141 |
142 radius = SkMinScalar(radius, kMAX_RADIUS); | 142 radius = SkMinScalar(radius, kMAX_BLUR_RADIUS); |
143 SkBlurMask::Quality blurQuality = | 143 SkBlurMask::Quality blurQuality = |
144 (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? | 144 (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? |
145 SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality; | 145 SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality; |
146 | 146 |
147 return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle, | 147 return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle, |
148 blurQuality, margin); | 148 blurQuality, margin); |
149 } | 149 } |
150 | 150 |
151 bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, | 151 bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, |
152 const SkMatrix& matrix, | 152 const SkMatrix& matrix, |
153 SkIPoint* margin, SkMask::CreateMode c
reateMode) const{ | 153 SkIPoint* margin, SkMask::CreateMode c
reateMode) const{ |
154 SkScalar radius; | 154 SkScalar radius; |
155 if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { | 155 if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { |
156 radius = fRadius; | 156 radius = fRadius; |
157 } else { | 157 } else { |
158 radius = matrix.mapRadius(fRadius); | 158 radius = matrix.mapRadius(fRadius); |
159 } | 159 } |
160 | 160 |
161 radius = SkMinScalar(radius, kMAX_RADIUS); | 161 radius = SkMinScalar(radius, kMAX_BLUR_RADIUS); |
162 | 162 |
163 return SkBlurMask::BlurRect(dst, r, radius, (SkBlurMask::Style)fBlurStyle, | 163 return SkBlurMask::BlurRect(dst, r, radius, (SkBlurMask::Style)fBlurStyle, |
164 margin, createMode); | 164 margin, createMode); |
165 } | 165 } |
166 | 166 |
167 #include "SkCanvas.h" | 167 #include "SkCanvas.h" |
168 | 168 |
169 static bool drawRectsIntoMask(const SkRect rects[], int count, SkMask* mask) { | 169 static bool drawRectsIntoMask(const SkRect rects[], int count, SkMask* mask) { |
170 rects[0].roundOut(&mask->fBounds); | 170 rects[0].roundOut(&mask->fBounds); |
171 mask->fRowBytes = SkAlign4(mask->fBounds.width()); | 171 mask->fRowBytes = SkAlign4(mask->fBounds.width()); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 } | 327 } |
328 } | 328 } |
329 patch->fMask.fBounds.offsetTo(0, 0); | 329 patch->fMask.fBounds.offsetTo(0, 0); |
330 patch->fOuterRect = dstM.fBounds; | 330 patch->fOuterRect = dstM.fBounds; |
331 patch->fCenter = center; | 331 patch->fCenter = center; |
332 return kTrue_FilterReturn; | 332 return kTrue_FilterReturn; |
333 } | 333 } |
334 | 334 |
335 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, | 335 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, |
336 SkRect* dst) const { | 336 SkRect* dst) const { |
337 dst->set(src.fLeft - fRadius, src.fTop - fRadius, | 337 SkScalar gpuPad, rasterPad; |
338 src.fRight + fRadius, src.fBottom + fRadius); | 338 |
| 339 { |
| 340 // GPU path |
| 341 SkScalar sigma = SkScalarMul(fRadius, kBLUR_SIGMA_SCALE); |
| 342 gpuPad = sigma * 3.0f; |
| 343 } |
| 344 |
| 345 { |
| 346 // raster path |
| 347 SkScalar radius = SkScalarMul(fRadius, SkBlurMask::kBlurRadiusFudgeFacto
r); |
| 348 |
| 349 radius = (radius + .5f) * 2.f; |
| 350 |
| 351 rasterPad = SkIntToScalar(SkScalarRoundToInt(radius * 3)/2); |
| 352 } |
| 353 |
| 354 SkScalar pad = SkMaxScalar(gpuPad, rasterPad); |
| 355 |
| 356 dst->set(src.fLeft - pad, src.fTop - pad, |
| 357 src.fRight + pad, src.fBottom + pad); |
339 } | 358 } |
340 | 359 |
341 SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer) | 360 SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer) |
342 : SkMaskFilter(buffer) { | 361 : SkMaskFilter(buffer) { |
343 fRadius = buffer.readScalar(); | 362 fRadius = buffer.readScalar(); |
344 fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt(); | 363 fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt(); |
345 fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag; | 364 fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag; |
346 SkASSERT(fRadius >= 0); | 365 SkASSERT(fRadius >= 0); |
347 SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount); | 366 SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount); |
348 } | 367 } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 } else { | 490 } else { |
472 str->append("None"); | 491 str->append("None"); |
473 } | 492 } |
474 str->append("))"); | 493 str->append("))"); |
475 } | 494 } |
476 #endif | 495 #endif |
477 | 496 |
478 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) | 497 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) |
479 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) | 498 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) |
480 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 499 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
OLD | NEW |