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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMa
trix&, | 62 virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMa
trix&, |
63 const SkIRect& clipBounds, | 63 const SkIRect& clipBounds, |
64 NinePatch*) const SK_OVERRIDE; | 64 NinePatch*) const SK_OVERRIDE; |
65 | 65 |
66 virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&, | 66 virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&, |
67 const SkIRect& clipBounds, | 67 const SkIRect& clipBounds, |
68 NinePatch*) const SK_OVERRIDE; | 68 NinePatch*) const SK_OVERRIDE; |
69 | 69 |
70 bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix, | 70 bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix, |
71 SkIPoint* margin, SkMask::CreateMode createMode) const; | 71 SkIPoint* margin, SkMask::CreateMode createMode) const; |
| 72 bool filterRRectMask(SkMask* dstM, const SkRRect& r, const SkMatrix& matrix, |
| 73 SkIPoint* margin, SkMask::CreateMode createMode) const; |
72 | 74 |
73 private: | 75 private: |
74 // To avoid unseemly allocation requests (esp. for finite platforms like | 76 // To avoid unseemly allocation requests (esp. for finite platforms like |
75 // handset) we limit the radius so something manageable. (as opposed to | 77 // handset) we limit the radius so something manageable. (as opposed to |
76 // a request like 10,000) | 78 // a request like 10,000) |
77 static const SkScalar kMAX_BLUR_SIGMA; | 79 static const SkScalar kMAX_BLUR_SIGMA; |
78 | 80 |
79 SkScalar fSigma; | 81 SkScalar fSigma; |
80 SkBlurMaskFilter::BlurStyle fBlurStyle; | 82 SkBlurMaskFilter::BlurStyle fBlurStyle; |
81 uint32_t fBlurFlags; | 83 uint32_t fBlurFlags; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 | 163 |
162 bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, | 164 bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, |
163 const SkMatrix& matrix, | 165 const SkMatrix& matrix, |
164 SkIPoint* margin, SkMask::CreateMode c
reateMode) const{ | 166 SkIPoint* margin, SkMask::CreateMode c
reateMode) const{ |
165 SkScalar sigma = computeXformedSigma(matrix); | 167 SkScalar sigma = computeXformedSigma(matrix); |
166 | 168 |
167 return SkBlurMask::BlurRect(sigma, dst, r, (SkBlurMask::Style)fBlurStyle, | 169 return SkBlurMask::BlurRect(sigma, dst, r, (SkBlurMask::Style)fBlurStyle, |
168 margin, createMode); | 170 margin, createMode); |
169 } | 171 } |
170 | 172 |
| 173 bool SkBlurMaskFilterImpl::filterRRectMask(SkMask* dst, const SkRRect& r, |
| 174 const SkMatrix& matrix, |
| 175 SkIPoint* margin, SkMask::CreateMode c
reateMode) const{ |
| 176 SkScalar sigma = computeXformedSigma(matrix); |
| 177 |
| 178 return SkBlurMask::BlurRRect(sigma, dst, r, (SkBlurMask::Style)fBlurStyle, |
| 179 margin, createMode); |
| 180 } |
| 181 |
171 #include "SkCanvas.h" | 182 #include "SkCanvas.h" |
172 | 183 |
173 static bool prepare_to_draw_into_mask(const SkRect& bounds, SkMask* mask) { | 184 static bool prepare_to_draw_into_mask(const SkRect& bounds, SkMask* mask) { |
174 SkASSERT(mask != NULL); | 185 SkASSERT(mask != NULL); |
175 | 186 |
176 bounds.roundOut(&mask->fBounds); | 187 bounds.roundOut(&mask->fBounds); |
177 mask->fRowBytes = SkAlign4(mask->fBounds.width()); | 188 mask->fRowBytes = SkAlign4(mask->fBounds.width()); |
178 mask->fFormat = SkMask::kA8_Format; | 189 mask->fFormat = SkMask::kA8_Format; |
179 const size_t size = mask->computeImageSize(); | 190 const size_t size = mask->computeImageSize(); |
180 mask->fImage = SkMask::AllocImage(size); | 191 mask->fImage = SkMask::AllocImage(size); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 canvas.drawPath(path, paint); | 248 canvas.drawPath(path, paint); |
238 } | 249 } |
239 return true; | 250 return true; |
240 } | 251 } |
241 | 252 |
242 static bool rect_exceeds(const SkRect& r, SkScalar v) { | 253 static bool rect_exceeds(const SkRect& r, SkScalar v) { |
243 return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v || | 254 return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v || |
244 r.width() > v || r.height() > v; | 255 r.width() > v || r.height() > v; |
245 } | 256 } |
246 | 257 |
| 258 #ifdef SK_IGNORE_FAST_RRECT_BLUR |
| 259 SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticRRect", fa
lse, "Use the faster analytic blur approach for ninepatch rects" ); |
| 260 #else |
| 261 SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticRRect", tr
ue, "Use the faster analytic blur approach for ninepatch round rects" ); |
| 262 #endif |
| 263 |
247 SkMaskFilter::FilterReturn | 264 SkMaskFilter::FilterReturn |
248 SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma
trix, | 265 SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma
trix, |
249 const SkIRect& clipBounds, | 266 const SkIRect& clipBounds, |
250 NinePatch* patch) const { | 267 NinePatch* patch) const { |
251 SkASSERT(patch != NULL); | 268 SkASSERT(patch != NULL); |
252 switch (rrect.getType()) { | 269 switch (rrect.getType()) { |
253 case SkRRect::kUnknown_Type: | 270 case SkRRect::kUnknown_Type: |
254 // Unknown should never be returned. | 271 // Unknown should never be returned. |
255 SkASSERT(false); | 272 SkASSERT(false); |
256 // Fall through. | 273 // Fall through. |
(...skipping 29 matching lines...) Expand all Loading... |
286 return kUnimplemented_FilterReturn; | 303 return kUnimplemented_FilterReturn; |
287 } | 304 } |
288 | 305 |
289 SkIPoint margin; | 306 SkIPoint margin; |
290 SkMask srcM, dstM; | 307 SkMask srcM, dstM; |
291 rrect.rect().roundOut(&srcM.fBounds); | 308 rrect.rect().roundOut(&srcM.fBounds); |
292 srcM.fImage = NULL; | 309 srcM.fImage = NULL; |
293 srcM.fFormat = SkMask::kA8_Format; | 310 srcM.fFormat = SkMask::kA8_Format; |
294 srcM.fRowBytes = 0; | 311 srcM.fRowBytes = 0; |
295 | 312 |
296 if (!this->filterMask(&dstM, srcM, matrix, &margin)) { | 313 bool filterResult = false; |
| 314 if (c_analyticBlurRRect) { |
| 315 // special case for fast round rect blur |
| 316 // don't actually do the blur the first time, just compute the correct s
ize |
| 317 filterResult = this->filterRRectMask(&dstM, rrect, matrix, &margin, |
| 318 SkMask::kJustComputeBounds_CreateMod
e); |
| 319 } |
| 320 |
| 321 if (!filterResult) { |
| 322 filterResult = this->filterMask(&dstM, srcM, matrix, &margin); |
| 323 } |
| 324 |
| 325 if (!filterResult) { |
297 return kFalse_FilterReturn; | 326 return kFalse_FilterReturn; |
298 } | 327 } |
299 | 328 |
300 // Now figure out the appropriate width and height of the smaller round rect
angle | 329 // Now figure out the appropriate width and height of the smaller round rect
angle |
301 // to stretch. It will take into account the larger radius per side as well
as double | 330 // to stretch. It will take into account the larger radius per side as well
as double |
302 // the margin, to account for inner and outer blur. | 331 // the margin, to account for inner and outer blur. |
303 const SkVector& UL = rrect.radii(SkRRect::kUpperLeft_Corner); | 332 const SkVector& UL = rrect.radii(SkRRect::kUpperLeft_Corner); |
304 const SkVector& UR = rrect.radii(SkRRect::kUpperRight_Corner); | 333 const SkVector& UR = rrect.radii(SkRRect::kUpperRight_Corner); |
305 const SkVector& LR = rrect.radii(SkRRect::kLowerRight_Corner); | 334 const SkVector& LR = rrect.radii(SkRRect::kLowerRight_Corner); |
306 const SkVector& LL = rrect.radii(SkRRect::kLowerLeft_Corner); | 335 const SkVector& LL = rrect.radii(SkRRect::kLowerLeft_Corner); |
(...skipping 23 matching lines...) Expand all Loading... |
330 SkRect smallR = SkRect::MakeWH(totalSmallWidth, totalSmallHeight); | 359 SkRect smallR = SkRect::MakeWH(totalSmallWidth, totalSmallHeight); |
331 | 360 |
332 SkRRect smallRR; | 361 SkRRect smallRR; |
333 SkVector radii[4]; | 362 SkVector radii[4]; |
334 radii[SkRRect::kUpperLeft_Corner] = UL; | 363 radii[SkRRect::kUpperLeft_Corner] = UL; |
335 radii[SkRRect::kUpperRight_Corner] = UR; | 364 radii[SkRRect::kUpperRight_Corner] = UR; |
336 radii[SkRRect::kLowerRight_Corner] = LR; | 365 radii[SkRRect::kLowerRight_Corner] = LR; |
337 radii[SkRRect::kLowerLeft_Corner] = LL; | 366 radii[SkRRect::kLowerLeft_Corner] = LL; |
338 smallRR.setRectRadii(smallR, radii); | 367 smallRR.setRectRadii(smallR, radii); |
339 | 368 |
340 if (!draw_rrect_into_mask(smallRR, &srcM)) { | 369 bool analyticBlurWorked = false; |
341 return kFalse_FilterReturn; | 370 if (c_analyticBlurRRect) { |
| 371 analyticBlurWorked = |
| 372 this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin, |
| 373 SkMask::kComputeBoundsAndRenderImage_CreateMod
e); |
342 } | 374 } |
343 | 375 |
344 SkAutoMaskFreeImage amf(srcM.fImage); | 376 if (!analyticBlurWorked) { |
| 377 if (!draw_rrect_into_mask(smallRR, &srcM)) { |
| 378 return kFalse_FilterReturn; |
| 379 } |
345 | 380 |
346 if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { | 381 SkAutoMaskFreeImage amf(srcM.fImage); |
347 return kFalse_FilterReturn; | 382 |
| 383 if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { |
| 384 return kFalse_FilterReturn; |
| 385 } |
348 } | 386 } |
349 | 387 |
350 patch->fMask.fBounds.offsetTo(0, 0); | 388 patch->fMask.fBounds.offsetTo(0, 0); |
351 patch->fOuterRect = dstM.fBounds; | 389 patch->fOuterRect = dstM.fBounds; |
352 patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; | 390 patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; |
353 patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; | 391 patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; |
354 return kTrue_FilterReturn; | 392 return kTrue_FilterReturn; |
355 } | 393 } |
356 | 394 |
357 #ifdef SK_IGNORE_FAST_RECT_BLUR | 395 #ifdef SK_IGNORE_FAST_RECT_BLUR |
(...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
895 } else { | 933 } else { |
896 str->append("None"); | 934 str->append("None"); |
897 } | 935 } |
898 str->append("))"); | 936 str->append("))"); |
899 } | 937 } |
900 #endif | 938 #endif |
901 | 939 |
902 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) | 940 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) |
903 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) | 941 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) |
904 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 942 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
OLD | NEW |