OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 The Android Open Source Project | 2 * Copyright 2011 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBitmap.h" | 8 #include "SkBitmap.h" |
9 #include "SkBlurImageFilter.h" | 9 #include "SkBlurImageFilter.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| 11 #include "SkImage_Base.h" |
| 12 #include "SkImagePriv.h" |
11 #include "SkReadBuffer.h" | 13 #include "SkReadBuffer.h" |
12 #include "SkWriteBuffer.h" | 14 #include "SkWriteBuffer.h" |
13 #include "SkGpuBlurUtils.h" | 15 #include "SkGpuBlurUtils.h" |
14 #include "SkBlurImage_opts.h" | 16 #include "SkBlurImage_opts.h" |
15 #if SK_SUPPORT_GPU | 17 #if SK_SUPPORT_GPU |
16 #include "GrContext.h" | 18 #include "GrContext.h" |
17 #endif | 19 #endif |
18 | 20 |
19 // This rather arbitrary-looking value results in a maximum box blur kernel size | 21 // This rather arbitrary-looking value results in a maximum box blur kernel size |
20 // of 1000 pixels on the raster path, which matches the WebKit and Firefox | 22 // of 1000 pixels on the raster path, which matches the WebKit and Firefox |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 *lowOffset = *highOffset = (d - 1) / 2; | 141 *lowOffset = *highOffset = (d - 1) / 2; |
140 *kernelSize3 = d; | 142 *kernelSize3 = d; |
141 } else { | 143 } else { |
142 *highOffset = d / 2; | 144 *highOffset = d / 2; |
143 *lowOffset = *highOffset - 1; | 145 *lowOffset = *highOffset - 1; |
144 *kernelSize3 = d + 1; | 146 *kernelSize3 = d + 1; |
145 } | 147 } |
146 } | 148 } |
147 | 149 |
148 bool SkBlurImageFilter::onFilterImage(Proxy* proxy, | 150 bool SkBlurImageFilter::onFilterImage(Proxy* proxy, |
149 const SkBitmap& source, const Context& ctx
, | 151 SkImage& source, const Context& ctx, |
150 SkBitmap* dst, SkIPoint* offset) const { | 152 SkAutoTUnref<SkImage>& dst, SkIPoint* offs
et) const { |
151 SkBitmap src = source; | 153 SkAutoTUnref<SkImage> src(SkRef(&source)); |
152 SkIPoint srcOffset = SkIPoint::Make(0, 0); | 154 SkIPoint srcOffset = SkIPoint::Make(0, 0); |
153 if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcO
ffset)) { | 155 if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, src, &srcOf
fset)) { |
154 return false; | 156 return false; |
155 } | 157 } |
156 | 158 |
157 if (src.colorType() != kN32_SkColorType) { | 159 #if 0 //TODO: colortype |
| 160 if (src->colorType() != kN32_SkColorType) { |
| 161 return false; |
| 162 } |
| 163 #endif |
| 164 |
| 165 SkIRect srcBounds, dstBounds; |
| 166 if (!this->applyCropRect(ctx, proxy, *src, &srcOffset, &srcBounds, src)) { |
158 return false; | 167 return false; |
159 } | 168 } |
160 | 169 |
161 SkIRect srcBounds, dstBounds; | 170 SkBitmap srcBitmap; |
162 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &srcBounds, &src)) { | 171 if (!as_IB(src)->getROPixels(&srcBitmap)) { |
| 172 return false; |
| 173 } |
| 174 src.reset(NULL); |
| 175 |
| 176 SkAutoLockPixels alp(srcBitmap); |
| 177 if (!srcBitmap.getPixels()) { |
163 return false; | 178 return false; |
164 } | 179 } |
165 | 180 |
166 SkAutoLockPixels alp(src); | 181 SkBitmap dstBitmap; |
167 if (!src.getPixels()) { | 182 if (!dstBitmap.tryAllocPixels( |
| 183 srcBitmap.info().makeWH(srcBounds.width(), srcBounds.height()))) { |
168 return false; | 184 return false; |
169 } | 185 } |
170 | 186 dstBitmap.getBounds(&dstBounds); |
171 if (!dst->tryAllocPixels(src.info().makeWH(srcBounds.width(), srcBounds.heig
ht()))) { | |
172 return false; | |
173 } | |
174 dst->getBounds(&dstBounds); | |
175 | 187 |
176 SkVector sigma = mapSigma(fSigma, ctx.ctm()); | 188 SkVector sigma = mapSigma(fSigma, ctx.ctm()); |
177 | 189 |
178 int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX; | 190 int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX; |
179 int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY; | 191 int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY; |
180 getBox3Params(sigma.x(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffs
etX); | 192 getBox3Params(sigma.x(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffs
etX); |
181 getBox3Params(sigma.y(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffs
etY); | 193 getBox3Params(sigma.y(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffs
etY); |
182 | 194 |
183 if (kernelSizeX < 0 || kernelSizeY < 0) { | 195 if (kernelSizeX < 0 || kernelSizeY < 0) { |
184 return false; | 196 return false; |
185 } | 197 } |
186 | 198 |
187 if (kernelSizeX == 0 && kernelSizeY == 0) { | 199 if (kernelSizeX == 0 && kernelSizeY == 0) { |
188 src.copyTo(dst, dst->colorType()); | 200 srcBitmap.copyTo(&dstBitmap, dstBitmap.colorType()); |
189 offset->fX = srcBounds.fLeft; | 201 offset->fX = srcBounds.fLeft; |
190 offset->fY = srcBounds.fTop; | 202 offset->fY = srcBounds.fTop; |
191 return true; | 203 return true; |
192 } | 204 } |
193 | 205 |
194 SkBitmap temp; | 206 SkBitmap temp; |
195 if (!temp.tryAllocPixels(dst->info())) { | 207 if (!temp.tryAllocPixels(dstBitmap.info())) { |
196 return false; | 208 return false; |
197 } | 209 } |
198 | 210 |
199 offset->fX = srcBounds.fLeft; | 211 int32_t resultX = srcBounds.fLeft; |
200 offset->fY = srcBounds.fTop; | 212 int32_t resultY = srcBounds.fTop; |
201 srcBounds.offset(-srcOffset); | 213 srcBounds.offset(-srcOffset); |
202 const SkPMColor* s = src.getAddr32(srcBounds.left(), srcBounds.top()); | 214 const SkPMColor* s = srcBitmap.getAddr32(srcBounds.left(), srcBounds.top()); |
203 SkPMColor* t = temp.getAddr32(0, 0); | 215 SkPMColor* t = temp.getAddr32(0, 0); |
204 SkPMColor* d = dst->getAddr32(0, 0); | 216 SkPMColor* d = dstBitmap.getAddr32(0, 0); |
205 int w = dstBounds.width(), h = dstBounds.height(); | 217 int w = dstBounds.width(), h = dstBounds.height(); |
206 int sw = src.rowBytesAsPixels(); | 218 int sw = srcBitmap.rowBytesAsPixels(); |
207 SkBoxBlurProc boxBlurX, boxBlurY, boxBlurXY, boxBlurYX; | 219 SkBoxBlurProc boxBlurX, boxBlurY, boxBlurXY, boxBlurYX; |
208 if (!SkBoxBlurGetPlatformProcs(&boxBlurX, &boxBlurY, &boxBlurXY, &boxBlurYX)
) { | 220 if (!SkBoxBlurGetPlatformProcs(&boxBlurX, &boxBlurY, &boxBlurXY, &boxBlurYX)
) { |
209 boxBlurX = boxBlur<kX, kX>; | 221 boxBlurX = boxBlur<kX, kX>; |
210 boxBlurY = boxBlur<kY, kY>; | 222 boxBlurY = boxBlur<kY, kY>; |
211 boxBlurXY = boxBlur<kX, kY>; | 223 boxBlurXY = boxBlur<kX, kY>; |
212 boxBlurYX = boxBlur<kY, kX>; | 224 boxBlurYX = boxBlur<kY, kX>; |
213 } | 225 } |
214 | 226 |
215 if (kernelSizeX > 0 && kernelSizeY > 0) { | 227 if (kernelSizeX > 0 && kernelSizeY > 0) { |
216 boxBlurX(s, sw, t, kernelSizeX, lowOffsetX, highOffsetX, w, h); | 228 boxBlurX(s, sw, t, kernelSizeX, lowOffsetX, highOffsetX, w, h); |
217 boxBlurX(t, w, d, kernelSizeX, highOffsetX, lowOffsetX, w, h); | 229 boxBlurX(t, w, d, kernelSizeX, highOffsetX, lowOffsetX, w, h); |
218 boxBlurXY(d, w, t, kernelSizeX3, highOffsetX, highOffsetX, w, h); | 230 boxBlurXY(d, w, t, kernelSizeX3, highOffsetX, highOffsetX, w, h); |
219 boxBlurX(t, h, d, kernelSizeY, lowOffsetY, highOffsetY, h, w); | 231 boxBlurX(t, h, d, kernelSizeY, lowOffsetY, highOffsetY, h, w); |
220 boxBlurX(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h, w); | 232 boxBlurX(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h, w); |
221 boxBlurXY(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h, w); | 233 boxBlurXY(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h, w); |
222 } else if (kernelSizeX > 0) { | 234 } else if (kernelSizeX > 0) { |
223 boxBlurX(s, sw, d, kernelSizeX, lowOffsetX, highOffsetX, w, h); | 235 boxBlurX(s, sw, d, kernelSizeX, lowOffsetX, highOffsetX, w, h); |
224 boxBlurX(d, w, t, kernelSizeX, highOffsetX, lowOffsetX, w, h); | 236 boxBlurX(d, w, t, kernelSizeX, highOffsetX, lowOffsetX, w, h); |
225 boxBlurX(t, w, d, kernelSizeX3, highOffsetX, highOffsetX, w, h); | 237 boxBlurX(t, w, d, kernelSizeX3, highOffsetX, highOffsetX, w, h); |
226 } else if (kernelSizeY > 0) { | 238 } else if (kernelSizeY > 0) { |
227 boxBlurYX(s, sw, d, kernelSizeY, lowOffsetY, highOffsetY, h, w); | 239 boxBlurYX(s, sw, d, kernelSizeY, lowOffsetY, highOffsetY, h, w); |
228 boxBlurX(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h, w); | 240 boxBlurX(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h, w); |
229 boxBlurXY(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h, w); | 241 boxBlurXY(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h, w); |
230 } | 242 } |
| 243 temp = SkBitmap(); |
| 244 SkImage* image = SkNewImageFromBitmap(dstBitmap, true, NULL); |
| 245 if (NULL == image) { |
| 246 return false; |
| 247 } |
| 248 dst.reset(image); |
| 249 offset->fX = resultX; |
| 250 offset->fY = resultY; |
231 return true; | 251 return true; |
232 } | 252 } |
233 | 253 |
234 | 254 |
235 void SkBlurImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const
{ | 255 void SkBlurImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const
{ |
236 if (getInput(0)) { | 256 if (getInput(0)) { |
237 getInput(0)->computeFastBounds(src, dst); | 257 getInput(0)->computeFastBounds(src, dst); |
238 } else { | 258 } else { |
239 *dst = src; | 259 *dst = src; |
240 } | 260 } |
241 | 261 |
242 dst->outset(SkScalarMul(fSigma.width(), SkIntToScalar(3)), | 262 dst->outset(SkScalarMul(fSigma.width(), SkIntToScalar(3)), |
243 SkScalarMul(fSigma.height(), SkIntToScalar(3))); | 263 SkScalarMul(fSigma.height(), SkIntToScalar(3))); |
244 } | 264 } |
245 | 265 |
246 bool SkBlurImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, | 266 bool SkBlurImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, |
247 SkIRect* dst) const { | 267 SkIRect* dst) const { |
248 SkIRect bounds = src; | 268 SkIRect bounds = src; |
249 SkVector sigma = mapSigma(fSigma, ctm); | 269 SkVector sigma = mapSigma(fSigma, ctm); |
250 bounds.outset(SkScalarCeilToInt(SkScalarMul(sigma.x(), SkIntToScalar(3))), | 270 bounds.outset(SkScalarCeilToInt(SkScalarMul(sigma.x(), SkIntToScalar(3))), |
251 SkScalarCeilToInt(SkScalarMul(sigma.y(), SkIntToScalar(3)))); | 271 SkScalarCeilToInt(SkScalarMul(sigma.y(), SkIntToScalar(3)))); |
252 if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) { | 272 if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) { |
253 return false; | 273 return false; |
254 } | 274 } |
255 *dst = bounds; | 275 *dst = bounds; |
256 return true; | 276 return true; |
257 } | 277 } |
258 | 278 |
259 bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const
Context& ctx, | 279 bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, SkImage& src, const Context
& ctx, |
260 SkBitmap* result, SkIPoint* offset) const
{ | 280 SkAutoTUnref<SkImage>& result, SkIPoint*
offset) const { |
261 #if SK_SUPPORT_GPU | 281 #if SK_SUPPORT_GPU |
262 SkBitmap input = src; | 282 SkAutoTUnref<SkImage> input(SkRef(&src)); |
263 SkIPoint srcOffset = SkIPoint::Make(0, 0); | 283 SkIPoint srcOffset = SkIPoint::Make(0, 0); |
264 if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, &input,
&srcOffset)) { | 284 if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, input, &
srcOffset)) { |
265 return false; | 285 return false; |
266 } | 286 } |
267 SkIRect rect; | 287 SkIRect rect; |
268 if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &rect, &input)) { | 288 if (!this->applyCropRect(ctx, proxy, *input, &srcOffset, &rect, input)) { |
269 return false; | 289 return false; |
270 } | 290 } |
271 GrTexture* source = input.getTexture(); | 291 GrTexture* source = input->getTexture(); |
272 SkVector sigma = mapSigma(fSigma, ctx.ctm()); | 292 SkVector sigma = mapSigma(fSigma, ctx.ctm()); |
273 offset->fX = rect.fLeft; | 293 offset->fX = rect.fLeft; |
274 offset->fY = rect.fTop; | 294 offset->fY = rect.fTop; |
275 rect.offset(-srcOffset); | 295 rect.offset(-srcOffset); |
276 SkAutoTUnref<GrTexture> tex(SkGpuBlurUtils::GaussianBlur(source->getContext(
), | 296 SkAutoTUnref<GrTexture> tex(SkGpuBlurUtils::GaussianBlur(source->getContext(
), |
277 source, | 297 source, |
278 false, | 298 false, |
279 SkRect::Make(rect), | 299 SkRect::Make(rect), |
280 true, | 300 true, |
281 sigma.x(), | 301 sigma.x(), |
282 sigma.y())); | 302 sigma.y())); |
283 WrapTexture(tex, rect.width(), rect.height(), result); | 303 if (!WrapTexture(tex, rect.width(), rect.height(), result)) { |
| 304 return false; |
| 305 } |
284 return true; | 306 return true; |
285 #else | 307 #else |
286 SkDEBUGFAIL("Should not call in GPU-less build"); | 308 SkDEBUGFAIL("Should not call in GPU-less build"); |
287 return false; | 309 return false; |
288 #endif | 310 #endif |
289 } | 311 } |
290 | 312 |
291 #ifndef SK_IGNORE_TO_STRING | 313 #ifndef SK_IGNORE_TO_STRING |
292 void SkBlurImageFilter::toString(SkString* str) const { | 314 void SkBlurImageFilter::toString(SkString* str) const { |
293 str->appendf("SkBlurImageFilter: ("); | 315 str->appendf("SkBlurImageFilter: ("); |
294 str->appendf("sigma: (%f, %f) input (", fSigma.fWidth, fSigma.fHeight); | 316 str->appendf("sigma: (%f, %f) input (", fSigma.fWidth, fSigma.fHeight); |
295 | 317 |
296 if (this->getInput(0)) { | 318 if (this->getInput(0)) { |
297 this->getInput(0)->toString(str); | 319 this->getInput(0)->toString(str); |
298 } | 320 } |
299 | 321 |
300 str->append("))"); | 322 str->append("))"); |
301 } | 323 } |
302 #endif | 324 #endif |
OLD | NEW |