Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(867)

Side by Side Diff: src/effects/SkBlurMaskFilter.cpp

Issue 12387099: first attempt to plumb fast blur code into skia mask filter (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: formatting fixes for Ben Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/effects/SkBlurMask.cpp ('K') | « src/effects/SkBlurMask.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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, bool perform_blur=true) 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
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, bool perform_blur) c onst{
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, perform_blur);
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
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, fa lse);
221 } else {
222 filterResult = this->filterMask(&dstM, srcM, matrix, &margin);
223 }
224
225 if (!filterResult) {
181 return kFalse_FilterReturn; 226 return kFalse_FilterReturn;
182 } 227 }
183 228
184 /* 229 /*
185 * smallR is the smallest version of 'rect' that will still guarantee that 230 * 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 231 * 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. 232 * 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 233 * Since our actual edge may be fractional we inset 1 more to be sure we
189 * don't miss any interior blur. 234 * don't miss any interior blur.
190 * x is an added pixel of blur, and { and } are the (fractional) edge 235 * 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
228 } 273 }
229 274
230 smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[ 0].bottom() - dy); 275 smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[ 0].bottom() - dy);
231 SkASSERT(!smallR[0].isEmpty()); 276 SkASSERT(!smallR[0].isEmpty());
232 if (2 == count) { 277 if (2 == count) {
233 smallR[1].set(rects[1].left(), rects[1].top(), 278 smallR[1].set(rects[1].left(), rects[1].top(),
234 rects[1].right() - dx, rects[1].bottom() - dy); 279 rects[1].right() - dx, rects[1].bottom() - dy);
235 SkASSERT(!smallR[1].isEmpty()); 280 SkASSERT(!smallR[1].isEmpty());
236 } 281 }
237 282
238 if (!drawRectsIntoMask(smallR, count, &srcM)) { 283 if (count > 1 || !c_analyticBlurNinepatch) {
239 return kFalse_FilterReturn; 284 if (!drawRectsIntoMask(smallR, count, &srcM)) {
240 } 285 return kFalse_FilterReturn;
286 }
241 287
242 SkAutoMaskFreeImage amf(srcM.fImage); 288 SkAutoMaskFreeImage amf(srcM.fImage);
243 289
244 if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { 290 if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) {
245 return kFalse_FilterReturn; 291 return kFalse_FilterReturn;
292 }
293 } else {
294 if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, tru e)) {
295 return kFalse_FilterReturn;
296 }
246 } 297 }
247 patch->fMask.fBounds.offsetTo(0, 0); 298 patch->fMask.fBounds.offsetTo(0, 0);
248 patch->fOuterRect = dstM.fBounds; 299 patch->fOuterRect = dstM.fBounds;
249 patch->fCenter = center; 300 patch->fCenter = center;
250 return kTrue_FilterReturn; 301 return kTrue_FilterReturn;
251 } 302 }
252 303
253 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, 304 void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src,
254 SkRect* dst) const { 305 SkRect* dst) const {
255 dst->set(src.fLeft - fRadius, src.fTop - fRadius, 306 dst->set(src.fLeft - fRadius, src.fTop - fRadius,
(...skipping 28 matching lines...) Expand all
284 info->fRadius = fRadius; 335 info->fRadius = fRadius;
285 info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnore Transform_BlurFlag); 336 info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnore Transform_BlurFlag);
286 info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQualit y_BlurFlag); 337 info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQualit y_BlurFlag);
287 } 338 }
288 return gBlurStyle2BlurType[fBlurStyle]; 339 return gBlurStyle2BlurType[fBlurStyle];
289 } 340 }
290 341
291 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) 342 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
292 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) 343 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
293 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 344 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
OLDNEW
« src/effects/SkBlurMask.cpp ('K') | « src/effects/SkBlurMask.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698