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

Side by Side Diff: src/core/SkImageFilter.cpp

Issue 1612953004: Image filters: Make a recursive, forward-mapping bounds traversal. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Update to ToT Created 4 years, 10 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 | « include/effects/SkTileImageFilter.h ('k') | src/core/SkLocalMatrixImageFilter.h » ('j') | 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 2012 The Android Open Source Project 2 * Copyright 2012 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 "SkImageFilter.h" 8 #include "SkImageFilter.h"
9 9
10 #include "SkBitmap.h" 10 #include "SkBitmap.h"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 } 59 }
60 if (fFlags & CropRect::kHasHeight_CropEdge) { 60 if (fFlags & CropRect::kHasHeight_CropEdge) {
61 str->appendf("%.2f", fRect.height()); 61 str->appendf("%.2f", fRect.height());
62 } else { 62 } else {
63 str->appendf("X"); 63 str->appendf("X");
64 } 64 }
65 str->appendf(") "); 65 str->appendf(") ");
66 } 66 }
67 #endif 67 #endif
68 68
69 bool SkImageFilter::CropRect::applyTo(const SkIRect& imageBounds, const Context& ctx, 69 void SkImageFilter::CropRect::applyTo(const SkIRect& imageBounds,
70 const SkMatrix& ctm,
70 SkIRect* cropped) const { 71 SkIRect* cropped) const {
71 *cropped = imageBounds; 72 *cropped = imageBounds;
72 if (fFlags) { 73 if (fFlags) {
73 SkRect devCropR; 74 SkRect devCropR;
74 ctx.ctm().mapRect(&devCropR, fRect); 75 ctm.mapRect(&devCropR, fRect);
75 const SkIRect devICropR = devCropR.roundOut(); 76 const SkIRect devICropR = devCropR.roundOut();
76 77
77 // Compute the left/top first, in case we have to read them to compute r ight/bottom 78 // Compute the left/top first, in case we have to read them to compute r ight/bottom
78 if (fFlags & kHasLeft_CropEdge) { 79 if (fFlags & kHasLeft_CropEdge) {
79 cropped->fLeft = devICropR.fLeft; 80 cropped->fLeft = devICropR.fLeft;
80 } 81 }
81 if (fFlags & kHasTop_CropEdge) { 82 if (fFlags & kHasTop_CropEdge) {
82 cropped->fTop = devICropR.fTop; 83 cropped->fTop = devICropR.fTop;
83 } 84 }
84 if (fFlags & kHasWidth_CropEdge) { 85 if (fFlags & kHasWidth_CropEdge) {
85 cropped->fRight = cropped->fLeft + devICropR.width(); 86 cropped->fRight = cropped->fLeft + devICropR.width();
86 } 87 }
87 if (fFlags & kHasHeight_CropEdge) { 88 if (fFlags & kHasHeight_CropEdge) {
88 cropped->fBottom = cropped->fTop + devICropR.height(); 89 cropped->fBottom = cropped->fTop + devICropR.height();
89 } 90 }
90 } 91 }
91 // Intersect against the clip bounds, in case the crop rect has
92 // grown the bounds beyond the original clip. This can happen for
93 // example in tiling, where the clip is much smaller than the filtered
94 // primitive. If we didn't do this, we would be processing the filter
95 // at the full crop rect size in every tile.
96 return cropped->intersect(ctx.clipBounds());
97 } 92 }
98 93
99 //////////////////////////////////////////////////////////////////////////////// /////////////////// 94 //////////////////////////////////////////////////////////////////////////////// ///////////////////
100 95
101 static int32_t next_image_filter_unique_id() { 96 static int32_t next_image_filter_unique_id() {
102 static int32_t gImageFilterUniqueID; 97 static int32_t gImageFilterUniqueID;
103 98
104 // Never return 0. 99 // Never return 0.
105 int32_t id; 100 int32_t id;
106 do { 101 do {
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 bool SkImageFilter::filterInput(int index, Proxy* proxy, const SkBitmap& src, 262 bool SkImageFilter::filterInput(int index, Proxy* proxy, const SkBitmap& src,
268 const Context& ctx, 263 const Context& ctx,
269 SkBitmap* result, SkIPoint* offset) const { 264 SkBitmap* result, SkIPoint* offset) const {
270 SkImageFilter* input = this->getInput(index); 265 SkImageFilter* input = this->getInput(index);
271 if (!input) { 266 if (!input) {
272 return true; 267 return true;
273 } 268 }
274 return input->filterImage(proxy, src, this->mapContext(ctx), result, offset) ; 269 return input->filterImage(proxy, src, this->mapContext(ctx), result, offset) ;
275 } 270 }
276 271
277 bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRec t* dst) const { 272 bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRec t* dst,
273 MapDirection direction) const {
278 SkASSERT(dst); 274 SkASSERT(dst);
279 return this->onFilterBounds(src, ctm, dst); 275 SkIRect bounds;
276 if (kReverse_MapDirection == direction) {
277 this->onFilterNodeBounds(src, ctm, &bounds, direction);
278 return this->onFilterBounds(bounds, ctm, dst, direction);
279 } else {
280 SkIRect temp;
281 if (!this->onFilterBounds(src, ctm, &bounds, direction)) {
282 return false;
283 }
284 this->onFilterNodeBounds(bounds, ctm, &temp, direction);
285 this->getCropRect().applyTo(temp, ctm, dst);
286 return true;
287 }
280 } 288 }
281 289
282 void SkImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { 290 void SkImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
283 if (0 == fInputCount) { 291 if (0 == fInputCount) {
284 *dst = src; 292 *dst = src;
285 return; 293 return;
286 } 294 }
287 if (this->getInput(0)) { 295 if (this->getInput(0)) {
288 this->getInput(0)->computeFastBounds(src, dst); 296 this->getInput(0)->computeFastBounds(src, dst);
289 } else { 297 } else {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 bool SkImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src, 397 bool SkImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src,
390 const SkIPoint& srcOffset, SkIRect* dstBounds, 398 const SkIPoint& srcOffset, SkIRect* dstBounds,
391 SkIRect* srcBounds) const { 399 SkIRect* srcBounds) const {
392 SkIRect storage; 400 SkIRect storage;
393 if (!srcBounds) { 401 if (!srcBounds) {
394 srcBounds = &storage; 402 srcBounds = &storage;
395 } 403 }
396 src.getBounds(srcBounds); 404 src.getBounds(srcBounds);
397 srcBounds->offset(srcOffset); 405 srcBounds->offset(srcOffset);
398 this->onFilterNodeBounds(*srcBounds, ctx.ctm(), dstBounds, kForward_MapDirec tion); 406 this->onFilterNodeBounds(*srcBounds, ctx.ctm(), dstBounds, kForward_MapDirec tion);
399 return fCropRect.applyTo(*dstBounds, ctx, dstBounds); 407 fCropRect.applyTo(*dstBounds, ctx.ctm(), dstBounds);
408 // Intersect against the clip bounds, in case the crop rect has
409 // grown the bounds beyond the original clip. This can happen for
410 // example in tiling, where the clip is much smaller than the filtered
411 // primitive. If we didn't do this, we would be processing the filter
412 // at the full crop rect size in every tile.
413 return dstBounds->intersect(ctx.clipBounds());
400 } 414 }
401 415
402 bool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitm ap& src, 416 bool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitm ap& src,
403 SkIPoint* srcOffset, SkIRect* bounds, SkBitmap * dst) const { 417 SkIPoint* srcOffset, SkIRect* bounds, SkBitmap * dst) const {
404 SkIRect srcBounds; 418 SkIRect srcBounds;
405 src.getBounds(&srcBounds); 419 src.getBounds(&srcBounds);
406 srcBounds.offset(*srcOffset); 420 srcBounds.offset(*srcOffset);
407 SkIRect dstBounds; 421 SkIRect dstBounds;
408 this->onFilterNodeBounds(srcBounds, ctx.ctm(), &dstBounds, kForward_MapDirec tion); 422 this->onFilterNodeBounds(srcBounds, ctx.ctm(), &dstBounds, kForward_MapDirec tion);
409 if (!fCropRect.applyTo(dstBounds, ctx, bounds)) { 423 fCropRect.applyTo(dstBounds, ctx.ctm(), bounds);
424 if (!bounds->intersect(ctx.clipBounds())) {
410 return false; 425 return false;
411 } 426 }
412 427
413 if (srcBounds.contains(*bounds)) { 428 if (srcBounds.contains(*bounds)) {
414 *dst = src; 429 *dst = src;
415 return true; 430 return true;
416 } else { 431 } else {
417 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), b ounds->height())); 432 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), b ounds->height()));
418 if (!device) { 433 if (!device) {
419 return false; 434 return false;
420 } 435 }
421 SkCanvas canvas(device); 436 SkCanvas canvas(device);
422 canvas.clear(0x00000000); 437 canvas.clear(0x00000000);
423 canvas.drawBitmap(src, srcOffset->x() - bounds->x(), srcOffset->y() - bo unds->y()); 438 canvas.drawBitmap(src, srcOffset->x() - bounds->x(), srcOffset->y() - bo unds->y());
424 *srcOffset = SkIPoint::Make(bounds->x(), bounds->y()); 439 *srcOffset = SkIPoint::Make(bounds->x(), bounds->y());
425 *dst = device->accessBitmap(false); 440 *dst = device->accessBitmap(false);
426 return true; 441 return true;
427 } 442 }
428 } 443 }
429 444
430 bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 445 bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
431 SkIRect* dst) const { 446 SkIRect* dst, MapDirection direction) const {
432 if (fInputCount < 1) { 447 if (fInputCount < 1) {
433 *dst = src; 448 *dst = src;
434 return true; 449 return true;
435 } 450 }
436 451
437 SkIRect bounds, totalBounds; 452 SkIRect totalBounds;
438 this->onFilterNodeBounds(src, ctm, &bounds, kReverse_MapDirection);
439 for (int i = 0; i < fInputCount; ++i) { 453 for (int i = 0; i < fInputCount; ++i) {
440 SkImageFilter* filter = this->getInput(i); 454 SkImageFilter* filter = this->getInput(i);
441 SkIRect rect = bounds; 455 SkIRect rect = src;
442 if (filter && !filter->filterBounds(bounds, ctm, &rect)) { 456 if (filter && !filter->filterBounds(src, ctm, &rect, direction)) {
443 return false; 457 return false;
444 } 458 }
445 if (0 == i) { 459 if (0 == i) {
446 totalBounds = rect; 460 totalBounds = rect;
447 } else { 461 } else {
448 totalBounds.join(rect); 462 totalBounds.join(rect);
449 } 463 }
450 } 464 }
451 465
452 // don't modify dst until now, so we don't accidentally change it in the 466 // don't modify dst until now, so we don't accidentally change it in the
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 } 672 }
659 return dev; 673 return dev;
660 } 674 }
661 675
662 bool SkImageFilter::DeviceProxy::filterImage(const SkImageFilter* filter, const SkBitmap& src, 676 bool SkImageFilter::DeviceProxy::filterImage(const SkImageFilter* filter, const SkBitmap& src,
663 const SkImageFilter::Context& ctx, 677 const SkImageFilter::Context& ctx,
664 SkBitmap* result, SkIPoint* offset) { 678 SkBitmap* result, SkIPoint* offset) {
665 return fDevice->filterImage(filter, src, ctx, result, offset); 679 return fDevice->filterImage(filter, src, ctx, result, offset);
666 } 680 }
667 681
OLDNEW
« no previous file with comments | « include/effects/SkTileImageFilter.h ('k') | src/core/SkLocalMatrixImageFilter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698