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

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: use actual CreateMode enum instead of bool 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
« no previous file with comments | « 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, 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
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
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
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
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
OLDNEW
« no previous file with comments | « src/effects/SkBlurMask.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698