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

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

Issue 1879643003: Switch AlphaThresholdFilter over to new onFilterImage interface (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address code review comments Created 4 years, 8 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
« no previous file with comments | « src/core/SkImageFilter.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 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
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 "SkAlphaThresholdFilter.h" 8 #include "SkAlphaThresholdFilter.h"
9 9
10 #include "SkBitmap.h" 10 #include "SkBitmap.h"
11 #include "SkDevice.h"
12 #include "SkReadBuffer.h" 11 #include "SkReadBuffer.h"
12 #include "SkSpecialImage.h"
13 #include "SkWriteBuffer.h" 13 #include "SkWriteBuffer.h"
14 #include "SkRegion.h" 14 #include "SkRegion.h"
15 #if SK_SUPPORT_GPU 15 #if SK_SUPPORT_GPU
16 #include "GrDrawContext.h" 16 #include "GrDrawContext.h"
17 #endif 17 #endif
18 18
19 class SK_API SkAlphaThresholdFilterImpl : public SkImageFilter { 19 class SK_API SkAlphaThresholdFilterImpl : public SkImageFilter {
20 public: 20 public:
21 SkAlphaThresholdFilterImpl(const SkRegion& region, SkScalar innerThreshold, 21 SkAlphaThresholdFilterImpl(const SkRegion& region, SkScalar innerThreshold,
22 SkScalar outerThreshold, sk_sp<SkImageFilter> inp ut); 22 SkScalar outerThreshold, sk_sp<SkImageFilter> inp ut,
23 const CropRect* cropRect = nullptr);
23 24
24 SK_TO_STRING_OVERRIDE() 25 SK_TO_STRING_OVERRIDE()
25 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAlphaThresholdFilterIm pl) 26 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAlphaThresholdFilterIm pl)
26 friend void SkAlphaThresholdFilter::InitializeFlattenables(); 27 friend void SkAlphaThresholdFilter::InitializeFlattenables();
27 28
28 protected: 29 protected:
29 void flatten(SkWriteBuffer&) const override; 30 void flatten(SkWriteBuffer&) const override;
30 31
31 bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&, 32 sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
32 SkBitmap* result, SkIPoint* offset) const overr ide; 33 SkIPoint* offset) const override;
34
33 #if SK_SUPPORT_GPU 35 #if SK_SUPPORT_GPU
34 bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&, 36 sk_sp<GrTexture> createMaskTexture(GrContext*, const SkMatrix&, const SkIRec t& bounds) const;
35 const SkIRect& bounds) const override;
36 #endif 37 #endif
37 38
38 private: 39 private:
39 SkRegion fRegion; 40 SkRegion fRegion;
40 SkScalar fInnerThreshold; 41 SkScalar fInnerThreshold;
41 SkScalar fOuterThreshold; 42 SkScalar fOuterThreshold;
42 typedef SkImageFilter INHERITED; 43 typedef SkImageFilter INHERITED;
43 }; 44 };
44 45
45 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkAlphaThresholdFilter) 46 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkAlphaThresholdFilter)
46 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAlphaThresholdFilterImpl) 47 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAlphaThresholdFilterImpl)
47 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 48 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
48 49
49 static SkScalar pin_0_1(SkScalar x) { 50 static SkScalar pin_0_1(SkScalar x) {
50 return SkMinScalar(SkMaxScalar(x, 0), 1); 51 return SkMinScalar(SkMaxScalar(x, 0), 1);
51 } 52 }
52 53
53 sk_sp<SkImageFilter> SkAlphaThresholdFilter::Make(const SkRegion& region, 54 sk_sp<SkImageFilter> SkAlphaThresholdFilter::Make(const SkRegion& region,
54 SkScalar innerThreshold, 55 SkScalar innerThreshold,
55 SkScalar outerThreshold, 56 SkScalar outerThreshold,
56 sk_sp<SkImageFilter> input) { 57 sk_sp<SkImageFilter> input,
58 const SkImageFilter::CropRect* cropRect) {
57 innerThreshold = pin_0_1(innerThreshold); 59 innerThreshold = pin_0_1(innerThreshold);
58 outerThreshold = pin_0_1(outerThreshold); 60 outerThreshold = pin_0_1(outerThreshold);
59 if (!SkScalarIsFinite(innerThreshold) || !SkScalarIsFinite(outerThreshold)) { 61 if (!SkScalarIsFinite(innerThreshold) || !SkScalarIsFinite(outerThreshold)) {
60 return nullptr; 62 return nullptr;
61 } 63 }
62 return sk_sp<SkImageFilter>(new SkAlphaThresholdFilterImpl(region, innerThre shold, 64 return sk_sp<SkImageFilter>(new SkAlphaThresholdFilterImpl(region, innerThre shold,
63 outerThreshold, s td::move(input))); 65 outerThreshold,
66 std::move(input),
Stephen White 2016/04/12 16:34:32 Nit: std::move() here seems to be overkill. Unless
robertphillips 2016/04/12 16:55:28 Yeah - this seems to be SOP for now. There is some
67 cropRect));
64 } 68 }
65 69
66 #if SK_SUPPORT_GPU 70 #if SK_SUPPORT_GPU
67 #include "GrContext.h" 71 #include "GrContext.h"
68 #include "GrCoordTransform.h" 72 #include "GrCoordTransform.h"
69 #include "GrFragmentProcessor.h" 73 #include "GrFragmentProcessor.h"
70 #include "GrInvariantOutput.h" 74 #include "GrInvariantOutput.h"
71 #include "GrTextureAccess.h" 75 #include "GrTextureAccess.h"
72 #include "effects/GrPorterDuffXferProcessor.h" 76 #include "effects/GrPorterDuffXferProcessor.h"
73 77
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 SkScalar inner = buffer.readScalar(); 274 SkScalar inner = buffer.readScalar();
271 SkScalar outer = buffer.readScalar(); 275 SkScalar outer = buffer.readScalar();
272 SkRegion rgn; 276 SkRegion rgn;
273 buffer.readRegion(&rgn); 277 buffer.readRegion(&rgn);
274 return SkAlphaThresholdFilter::Make(rgn, inner, outer, common.getInput(0)); 278 return SkAlphaThresholdFilter::Make(rgn, inner, outer, common.getInput(0));
275 } 279 }
276 280
277 SkAlphaThresholdFilterImpl::SkAlphaThresholdFilterImpl(const SkRegion& region, 281 SkAlphaThresholdFilterImpl::SkAlphaThresholdFilterImpl(const SkRegion& region,
278 SkScalar innerThreshold, 282 SkScalar innerThreshold,
279 SkScalar outerThreshold, 283 SkScalar outerThreshold,
280 sk_sp<SkImageFilter> inpu t) 284 sk_sp<SkImageFilter> inpu t,
281 : INHERITED(&input, 1, nullptr) 285 const CropRect* cropRect)
286 : INHERITED(&input, 1, cropRect)
282 , fRegion(region) 287 , fRegion(region)
283 , fInnerThreshold(innerThreshold) 288 , fInnerThreshold(innerThreshold)
284 , fOuterThreshold(outerThreshold) { 289 , fOuterThreshold(outerThreshold) {
285 } 290 }
286 291
287 #if SK_SUPPORT_GPU 292 #if SK_SUPPORT_GPU
288 bool SkAlphaThresholdFilterImpl::asFragmentProcessor(GrFragmentProcessor** fp, 293 sk_sp<GrTexture> SkAlphaThresholdFilterImpl::createMaskTexture(GrContext* contex t,
289 GrTexture* texture, 294 const SkMatrix& i nMatrix,
290 const SkMatrix& inMatrix, 295 const SkIRect& bo unds) const {
291 const SkIRect& bounds) cons t { 296 GrSurfaceDesc maskDesc;
292 if (fp) { 297 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
293 GrContext* context = texture->getContext(); 298 maskDesc.fConfig = kAlpha_8_GrPixelConfig;
294 GrSurfaceDesc maskDesc; 299 } else {
295 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { 300 maskDesc.fConfig = kRGBA_8888_GrPixelConfig;
296 maskDesc.fConfig = kAlpha_8_GrPixelConfig; 301 }
297 } else { 302 maskDesc.fFlags = kRenderTarget_GrSurfaceFlag;
298 maskDesc.fConfig = kRGBA_8888_GrPixelConfig; 303 // Add one pixel of border to ensure that clamp mode will be all zeros
299 } 304 // the outside.
300 maskDesc.fFlags = kRenderTarget_GrSurfaceFlag; 305 maskDesc.fWidth = bounds.width();
301 // Add one pixel of border to ensure that clamp mode will be all zeros 306 maskDesc.fHeight = bounds.height();
302 // the outside. 307 sk_sp<GrTexture> maskTexture(context->textureProvider()->createApproxTexture (maskDesc));
303 maskDesc.fWidth = bounds.width(); 308 if (!maskTexture) {
304 maskDesc.fHeight = bounds.height(); 309 return nullptr;
305 SkAutoTUnref<GrTexture> maskTexture( 310 }
306 context->textureProvider()->createApproxTexture(maskDesc));
307 if (!maskTexture) {
308 return false;
309 }
310 311
311 SkAutoTUnref<GrDrawContext> drawContext( 312 sk_sp<GrDrawContext> drawContext(context->drawContext(maskTexture->asRenderT arget()));
312 context->drawContext(maskTexture->as RenderTarget())); 313 if (!drawContext) {
313 if (drawContext) { 314 return nullptr;
314 GrPaint grPaint; 315 }
315 grPaint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
316 SkRegion::Iterator iter(fRegion);
317 drawContext->clear(nullptr, 0x0, true);
318 316
319 GrClip clip(SkRect::Make(SkIRect::MakeWH(bounds.width(), bounds.heig ht()))); 317 GrPaint grPaint;
320 while (!iter.done()) { 318 grPaint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
321 SkRect rect = SkRect::Make(iter.rect()); 319 SkRegion::Iterator iter(fRegion);
322 drawContext->drawRect(clip, grPaint, inMatrix, rect); 320 drawContext->clear(nullptr, 0x0, true);
323 iter.next();
324 }
325 }
326 321
327 *fp = AlphaThresholdEffect::Create(texture, 322 GrClip clip(SkRect::Make(SkIRect::MakeWH(bounds.width(), bounds.height())));
328 maskTexture, 323 while (!iter.done()) {
329 fInnerThreshold, 324 SkRect rect = SkRect::Make(iter.rect());
330 fOuterThreshold, 325 drawContext->drawRect(clip, grPaint, inMatrix, rect);
331 bounds); 326 iter.next();
332 } 327 }
333 return true; 328
329 return maskTexture;
334 } 330 }
335 #endif 331 #endif
336 332
337 void SkAlphaThresholdFilterImpl::flatten(SkWriteBuffer& buffer) const { 333 void SkAlphaThresholdFilterImpl::flatten(SkWriteBuffer& buffer) const {
338 this->INHERITED::flatten(buffer); 334 this->INHERITED::flatten(buffer);
339 buffer.writeScalar(fInnerThreshold); 335 buffer.writeScalar(fInnerThreshold);
340 buffer.writeScalar(fOuterThreshold); 336 buffer.writeScalar(fOuterThreshold);
341 buffer.writeRegion(fRegion); 337 buffer.writeRegion(fRegion);
342 } 338 }
343 339
344 bool SkAlphaThresholdFilterImpl::onFilterImageDeprecated(Proxy* proxy, const SkB itmap& src, 340 sk_sp<SkSpecialImage> SkAlphaThresholdFilterImpl::onFilterImage(SkSpecialImage* source,
345 const Context& ctx, SkB itmap* dst, 341 const Context& c tx,
346 SkIPoint* offset) const { 342 SkIPoint* offset ) const {
343 SkIPoint inputOffset = SkIPoint::Make(0, 0);
344 sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset)) ;
345 if (!input) {
346 return nullptr;
347 }
347 348
348 if (src.colorType() != kN32_SkColorType) { 349 const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y (),
349 return false; 350 input->width(), input->height( ));
351
352 SkIRect bounds;
353 if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
354 return nullptr;
350 } 355 }
351 356
357 #if SK_SUPPORT_GPU
358 if (source->isTextureBacked()) {
359 GrContext* context = source->getContext();
360
361 sk_sp<GrTexture> inputTexture(input->asTextureRef(context));
362 SkASSERT(inputTexture);
363
364 offset->fX = bounds.left();
365 offset->fY = bounds.top();
366
367 bounds.offset(-inputOffset);
368
369 SkMatrix matrix(ctx.ctm());
370 matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bound s.top()));
371
372 sk_sp<GrTexture> maskTexture(this->createMaskTexture(context, matrix, bo unds));
373 if (!maskTexture) {
374 return nullptr;
375 }
376
377 // SRGBTODO: handle sRGB here
378 sk_sp<GrFragmentProcessor> fp(AlphaThresholdEffect::Create(inputTexture. get(),
379 maskTexture.g et(),
380 fInnerThresho ld,
381 fOuterThresho ld,
382 bounds));
383 if (!fp) {
384 return nullptr;
385 }
386
387 return DrawWithFP(context, std::move(fp), bounds, source->internal_getPr oxy());
Stephen White 2016/04/12 16:34:32 Much nicer, thanks! (Again, I'm not a fan with pe
robertphillips 2016/04/12 16:55:28 Acknowledged.
388 }
389 #endif
390
391 SkBitmap inputBM;
392
393 if (!input->getROPixels(&inputBM)) {
394 return nullptr;
395 }
396
397 if (inputBM.colorType() != kN32_SkColorType) {
398 return nullptr;
399 }
400
401 SkAutoLockPixels inputLock(inputBM);
402
403 if (!inputBM.getPixels() || inputBM.width() <= 0 || inputBM.height() <= 0) {
404 return nullptr;
405 }
406
407
352 SkMatrix localInverse; 408 SkMatrix localInverse;
353 if (!ctx.ctm().invert(&localInverse)) { 409 if (!ctx.ctm().invert(&localInverse)) {
354 return false; 410 return nullptr;
355 } 411 }
356 412
357 SkAutoLockPixels alp(src); 413 SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(),
358 SkASSERT(src.getPixels()); 414 inputBM.alphaType());
359 if (!src.getPixels() || src.width() <= 0 || src.height() <= 0) { 415
360 return false; 416 SkBitmap dst;
417 if (!dst.tryAllocPixels(info)) {
418 return nullptr;
361 } 419 }
362 420
363 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(src.width(), src.heigh t())); 421 SkAutoLockPixels dstLock(dst);
364 if (!device) {
365 return false;
366 }
367 *dst = device->accessBitmap(false);
368 SkAutoLockPixels alp_dst(*dst);
369 422
370 U8CPU innerThreshold = (U8CPU)(fInnerThreshold * 0xFF); 423 U8CPU innerThreshold = (U8CPU)(fInnerThreshold * 0xFF);
371 U8CPU outerThreshold = (U8CPU)(fOuterThreshold * 0xFF); 424 U8CPU outerThreshold = (U8CPU)(fOuterThreshold * 0xFF);
372 SkColor* sptr = src.getAddr32(0, 0); 425 SkColor* dptr = dst.getAddr32(0, 0);
373 SkColor* dptr = dst->getAddr32(0, 0); 426 int dstWidth = dst.width(), dstHeight = dst.height();
374 int width = src.width(), height = src.height(); 427 for (int y = 0; y < dstHeight; ++y) {
375 for (int y = 0; y < height; ++y) { 428 const SkColor* sptr = inputBM.getAddr32(bounds.fLeft, bounds.fTop+y);
376 for (int x = 0; x < width; ++x) { 429
377 const SkColor& source = sptr[y * width + x]; 430 for (int x = 0; x < dstWidth; ++x) {
378 SkColor output_color(source); 431 const SkColor& source = sptr[x];
432 SkColor outputColor(source);
379 SkPoint position; 433 SkPoint position;
380 localInverse.mapXY((SkScalar)x, (SkScalar)y, &position); 434 localInverse.mapXY((SkScalar)x + bounds.fLeft, (SkScalar)y + bounds. fTop, &position);
381 if (fRegion.contains((int32_t)position.x(), (int32_t)position.y())) { 435 if (fRegion.contains((int32_t)position.x(), (int32_t)position.y())) {
382 if (SkColorGetA(source) < innerThreshold) { 436 if (SkColorGetA(source) < innerThreshold) {
383 U8CPU alpha = SkColorGetA(source); 437 U8CPU alpha = SkColorGetA(source);
384 if (alpha == 0) 438 if (alpha == 0) {
385 alpha = 1; 439 alpha = 1;
440 }
386 float scale = (float)innerThreshold / alpha; 441 float scale = (float)innerThreshold / alpha;
387 output_color = SkColorSetARGB(innerThreshold, 442 outputColor = SkColorSetARGB(innerThreshold,
388 (U8CPU)(SkColorGetR(source) * scale), 443 (U8CPU)(SkColorGetR(source) * scale),
389 (U8CPU)(SkColorGetG(source) * scale), 444 (U8CPU)(SkColorGetG(source) * scale),
390 (U8CPU)(SkColorGetB(source) * scale)); 445 (U8CPU)(SkColorGetB(source) * scale));
391 } 446 }
392 } else { 447 } else {
393 if (SkColorGetA(source) > outerThreshold) { 448 if (SkColorGetA(source) > outerThreshold) {
394 float scale = (float)outerThreshold / SkColorGetA(source); 449 float scale = (float)outerThreshold / SkColorGetA(source);
395 output_color = SkColorSetARGB(outerThreshold, 450 outputColor = SkColorSetARGB(outerThreshold,
396 (U8CPU)(SkColorGetR(source) * scale), 451 (U8CPU)(SkColorGetR(source) * scale),
397 (U8CPU)(SkColorGetG(source) * scale), 452 (U8CPU)(SkColorGetG(source) * scale),
398 (U8CPU)(SkColorGetB(source) * scale)); 453 (U8CPU)(SkColorGetB(source) * scale));
399 } 454 }
400 } 455 }
401 dptr[y * dst->width() + x] = output_color; 456 dptr[y * dstWidth + x] = outputColor;
402 } 457 }
403 } 458 }
404 459
405 return true; 460 offset->fX = bounds.left();
461 offset->fY = bounds.top();
462 return SkSpecialImage::MakeFromRaster(source->internal_getProxy(),
463 SkIRect::MakeWH(bounds.width(), bounds .height()),
464 dst);
406 } 465 }
407 466
408 #ifndef SK_IGNORE_TO_STRING 467 #ifndef SK_IGNORE_TO_STRING
409 void SkAlphaThresholdFilterImpl::toString(SkString* str) const { 468 void SkAlphaThresholdFilterImpl::toString(SkString* str) const {
410 str->appendf("SkAlphaThresholdImageFilter: ("); 469 str->appendf("SkAlphaThresholdImageFilter: (");
411 str->appendf("inner: %f outer: %f", fInnerThreshold, fOuterThreshold); 470 str->appendf("inner: %f outer: %f", fInnerThreshold, fOuterThreshold);
412 str->append(")"); 471 str->append(")");
413 } 472 }
414 #endif 473 #endif
OLDNEW
« no previous file with comments | « src/core/SkImageFilter.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698