| 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" |
| 11 #include "SkFlattenableBuffers.h" | 11 #include "SkFlattenableBuffers.h" |
| 12 #include "SkMaskFilter.h" | 12 #include "SkMaskFilter.h" |
| 13 #include "SkBounder.h" |
| 14 #include "SkRasterClip.h" |
| 15 #include "SkRTConf.h" |
| 13 | 16 |
| 14 class SkBlurMaskFilterImpl : public SkMaskFilter { | 17 class SkBlurMaskFilterImpl : public SkMaskFilter { |
| 15 public: | 18 public: |
| 16 SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle, | 19 SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle, |
| 17 uint32_t flags); | 20 uint32_t flags); |
| 18 | 21 |
| 19 // overrides from SkMaskFilter | 22 // overrides from SkMaskFilter |
| 20 virtual SkMask::Format getFormat() const SK_OVERRIDE; | 23 virtual SkMask::Format getFormat() const SK_OVERRIDE; |
| 21 virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, | 24 virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, |
| 22 SkIPoint* margin) const SK_OVERRIDE; | 25 SkIPoint* margin) const SK_OVERRIDE; |
| 26 |
| 23 virtual BlurType asABlur(BlurInfo*) const SK_OVERRIDE; | 27 virtual BlurType asABlur(BlurInfo*) const SK_OVERRIDE; |
| 24 virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; | 28 virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; |
| 25 | 29 |
| 26 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) | 30 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) |
| 27 | 31 |
| 28 protected: | 32 protected: |
| 29 virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMa
trix&, | 33 virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMa
trix&, |
| 30 const SkIRect& clipBounds, | 34 const SkIRect& clipBounds, |
| 31 NinePatch*) const SK_OVERRIDE; | 35 NinePatch*) const SK_OVERRIDE; |
| 36 |
| 37 bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix, |
| 38 SkIPoint* margin, SkMask::CreateMode createMode) const; |
| 32 | 39 |
| 33 private: | 40 private: |
| 34 SkScalar fRadius; | 41 SkScalar fRadius; |
| 35 SkBlurMaskFilter::BlurStyle fBlurStyle; | 42 SkBlurMaskFilter::BlurStyle fBlurStyle; |
| 36 uint32_t fBlurFlags; | 43 uint32_t fBlurFlags; |
| 37 | 44 |
| 38 SkBlurMaskFilterImpl(SkFlattenableReadBuffer&); | 45 SkBlurMaskFilterImpl(SkFlattenableReadBuffer&); |
| 39 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; | 46 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; |
| 40 | 47 |
| 41 typedef SkMaskFilter INHERITED; | 48 typedef SkMaskFilter INHERITED; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 | 106 |
| 100 #ifndef SK_DISABLE_SEPARABLE_MASK_BLUR | 107 #ifndef SK_DISABLE_SEPARABLE_MASK_BLUR |
| 101 return SkBlurMask::BlurSeparable(dst, src, radius, (SkBlurMask::Style)fBlurS
tyle, | 108 return SkBlurMask::BlurSeparable(dst, src, radius, (SkBlurMask::Style)fBlurS
tyle, |
| 102 blurQuality, margin); | 109 blurQuality, margin); |
| 103 #else | 110 #else |
| 104 return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle, | 111 return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle, |
| 105 blurQuality, margin); | 112 blurQuality, margin); |
| 106 #endif | 113 #endif |
| 107 } | 114 } |
| 108 | 115 |
| 116 bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, |
| 117 const SkMatrix& matrix, |
| 118 SkIPoint* margin, SkMask::CreateMode c
reateMode) const{ |
| 119 SkScalar radius; |
| 120 if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { |
| 121 radius = fRadius; |
| 122 } else { |
| 123 radius = matrix.mapRadius(fRadius); |
| 124 } |
| 125 |
| 126 // To avoid unseemly allocation requests (esp. for finite platforms like |
| 127 // handset) we limit the radius so something manageable. (as opposed to |
| 128 // a request like 10,000) |
| 129 static const SkScalar MAX_RADIUS = SkIntToScalar(128); |
| 130 radius = SkMinScalar(radius, MAX_RADIUS); |
| 131 |
| 132 return SkBlurMask::BlurRect(dst, r, radius, (SkBlurMask::Style)fBlurStyle, |
| 133 margin, createMode); |
| 134 } |
| 135 |
| 109 #include "SkCanvas.h" | 136 #include "SkCanvas.h" |
| 110 | 137 |
| 111 static bool drawRectsIntoMask(const SkRect rects[], int count, SkMask* mask) { | 138 static bool drawRectsIntoMask(const SkRect rects[], int count, SkMask* mask) { |
| 112 rects[0].roundOut(&mask->fBounds); | 139 rects[0].roundOut(&mask->fBounds); |
| 113 mask->fRowBytes = SkAlign4(mask->fBounds.width()); | 140 mask->fRowBytes = SkAlign4(mask->fBounds.width()); |
| 114 mask->fFormat = SkMask::kA8_Format; | 141 mask->fFormat = SkMask::kA8_Format; |
| 115 size_t size = mask->computeImageSize(); | 142 size_t size = mask->computeImageSize(); |
| 116 mask->fImage = SkMask::AllocImage(size); | 143 mask->fImage = SkMask::AllocImage(size); |
| 117 if (NULL == mask->fImage) { | 144 if (NULL == mask->fImage) { |
| 118 return false; | 145 return false; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 143 canvas.drawPath(path, paint); | 170 canvas.drawPath(path, paint); |
| 144 } | 171 } |
| 145 return true; | 172 return true; |
| 146 } | 173 } |
| 147 | 174 |
| 148 static bool rect_exceeds(const SkRect& r, SkScalar v) { | 175 static bool rect_exceeds(const SkRect& r, SkScalar v) { |
| 149 return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v || | 176 return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v || |
| 150 r.width() > v || r.height() > v; | 177 r.width() > v || r.height() > v; |
| 151 } | 178 } |
| 152 | 179 |
| 180 SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch",
|
| 181 #ifdef SK_IGNORE_FAST_RECT_BLUR |
| 182 false, |
| 183 #else |
| 184 true, |
| 185 #endif |
| 186 "Use the faster analytic blur approach for ninepatch rects" ); |
| 187 |
| 153 SkMaskFilter::FilterReturn | 188 SkMaskFilter::FilterReturn |
| 154 SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, | 189 SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, |
| 155 const SkMatrix& matrix, | 190 const SkMatrix& matrix, |
| 156 const SkIRect& clipBounds, | 191 const SkIRect& clipBounds, |
| 157 NinePatch* patch) const { | 192 NinePatch* patch) const { |
| 158 if (count < 1 || count > 2) { | 193 if (count < 1 || count > 2) { |
| 159 return kUnimplemented_FilterReturn; | 194 return kUnimplemented_FilterReturn; |
| 160 } | 195 } |
| 161 | 196 |
| 162 // TODO: report correct metrics for innerstyle, where we do not grow the | 197 // TODO: report correct metrics for innerstyle, where we do not grow the |
| 163 // total bounds, but we do need an inset the size of our blur-radius | 198 // total bounds, but we do need an inset the size of our blur-radius |
| 164 if (SkBlurMaskFilter::kInner_BlurStyle == fBlurStyle) { | 199 if (SkBlurMaskFilter::kInner_BlurStyle == fBlurStyle) { |
| 165 return kUnimplemented_FilterReturn; | 200 return kUnimplemented_FilterReturn; |
| 166 } | 201 } |
| 167 | 202 |
| 168 // TODO: take clipBounds into account to limit our coordinates up front | 203 // TODO: take clipBounds into account to limit our coordinates up front |
| 169 // for now, just skip too-large src rects (to take the old code path). | 204 // for now, just skip too-large src rects (to take the old code path). |
| 170 if (rect_exceeds(rects[0], SkIntToScalar(32767))) { | 205 if (rect_exceeds(rects[0], SkIntToScalar(32767))) { |
| 171 return kUnimplemented_FilterReturn; | 206 return kUnimplemented_FilterReturn; |
| 172 } | 207 } |
| 173 | 208 |
| 174 SkIPoint margin; | 209 SkIPoint margin; |
| 175 SkMask srcM, dstM; | 210 SkMask srcM, dstM; |
| 176 rects[0].roundOut(&srcM.fBounds); | 211 rects[0].roundOut(&srcM.fBounds); |
| 177 srcM.fImage = NULL; | 212 srcM.fImage = NULL; |
| 178 srcM.fFormat = SkMask::kA8_Format; | 213 srcM.fFormat = SkMask::kA8_Format; |
| 179 srcM.fRowBytes = 0; | 214 srcM.fRowBytes = 0; |
| 180 if (!this->filterMask(&dstM, srcM, matrix, &margin)) { | 215 |
| 216 bool filterResult = false; |
| 217 if (count == 1 && c_analyticBlurNinepatch) { |
| 218 // special case for fast rect blur |
| 219 // don't actually do the blur the first time, just compute the correct s
ize |
| 220 filterResult = this->filterRectMask(&dstM, rects[0], matrix, &margin, |
| 221 SkMask::kJustComputeBounds_CreateMod
e); |
| 222 } else { |
| 223 filterResult = this->filterMask(&dstM, srcM, matrix, &margin); |
| 224 } |
| 225 |
| 226 if (!filterResult) { |
| 181 return kFalse_FilterReturn; | 227 return kFalse_FilterReturn; |
| 182 } | 228 } |
| 183 | 229 |
| 184 /* | 230 /* |
| 185 * smallR is the smallest version of 'rect' that will still guarantee that | 231 * smallR is the smallest version of 'rect' that will still guarantee that |
| 186 * we get the same blur results on all edges, plus 1 center row/col that is | 232 * we get the same blur results on all edges, plus 1 center row/col that is |
| 187 * representative of the extendible/stretchable edges of the ninepatch. | 233 * representative of the extendible/stretchable edges of the ninepatch. |
| 188 * Since our actual edge may be fractional we inset 1 more to be sure we | 234 * Since our actual edge may be fractional we inset 1 more to be sure we |
| 189 * don't miss any interior blur. | 235 * don't miss any interior blur. |
| 190 * x is an added pixel of blur, and { and } are the (fractional) edge | 236 * x is an added pixel of blur, and { and } are the (fractional) edge |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 } | 274 } |
| 229 | 275 |
| 230 smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[
0].bottom() - dy); | 276 smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[
0].bottom() - dy); |
| 231 SkASSERT(!smallR[0].isEmpty()); | 277 SkASSERT(!smallR[0].isEmpty()); |
| 232 if (2 == count) { | 278 if (2 == count) { |
| 233 smallR[1].set(rects[1].left(), rects[1].top(), | 279 smallR[1].set(rects[1].left(), rects[1].top(), |
| 234 rects[1].right() - dx, rects[1].bottom() - dy); | 280 rects[1].right() - dx, rects[1].bottom() - dy); |
| 235 SkASSERT(!smallR[1].isEmpty()); | 281 SkASSERT(!smallR[1].isEmpty()); |
| 236 } | 282 } |
| 237 | 283 |
| 238 if (!drawRectsIntoMask(smallR, count, &srcM)) { | 284 if (count > 1 || !c_analyticBlurNinepatch) { |
| 239 return kFalse_FilterReturn; | 285 if (!drawRectsIntoMask(smallR, count, &srcM)) { |
| 240 } | 286 return kFalse_FilterReturn; |
| 287 } |
| 241 | 288 |
| 242 SkAutoMaskFreeImage amf(srcM.fImage); | 289 SkAutoMaskFreeImage amf(srcM.fImage); |
| 243 | 290 |
| 244 if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { | 291 if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { |
| 245 return kFalse_FilterReturn; | 292 return kFalse_FilterReturn; |
| 293 } |
| 294 } else { |
| 295 if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, |
| 296 SkMask::kComputeBoundsAndRenderImage_CreateMod
e)) { |
| 297 return kFalse_FilterReturn; |
| 298 } |
| 246 } | 299 } |
| 247 patch->fMask.fBounds.offsetTo(0, 0); | 300 patch->fMask.fBounds.offsetTo(0, 0); |
| 248 patch->fOuterRect = dstM.fBounds; | 301 patch->fOuterRect = dstM.fBounds; |
| 249 patch->fCenter = center; | 302 patch->fCenter = center; |
| 250 return kTrue_FilterReturn; | 303 return kTrue_FilterReturn; |
| 251 } | 304 } |
| 252 | 305 |
| 253 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, | 306 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, |
| 254 SkRect* dst) const { | 307 SkRect* dst) const { |
| 255 dst->set(src.fLeft - fRadius, src.fTop - fRadius, | 308 dst->set(src.fLeft - fRadius, src.fTop - fRadius, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 284 info->fRadius = fRadius; | 337 info->fRadius = fRadius; |
| 285 info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnore
Transform_BlurFlag); | 338 info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnore
Transform_BlurFlag); |
| 286 info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQualit
y_BlurFlag); | 339 info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQualit
y_BlurFlag); |
| 287 } | 340 } |
| 288 return gBlurStyle2BlurType[fBlurStyle]; | 341 return gBlurStyle2BlurType[fBlurStyle]; |
| 289 } | 342 } |
| 290 | 343 |
| 291 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) | 344 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) |
| 292 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) | 345 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) |
| 293 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 346 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| OLD | NEW |