| OLD | NEW |
| 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 #include "SkImageFilterCacheKey.h" | 9 #include "SkImageFilterCacheKey.h" |
| 10 | 10 |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 SkAutoTUnref<SkSpecialImage> tmp(input->onFilterImage(specialSrc.get(), | 283 SkAutoTUnref<SkSpecialImage> tmp(input->onFilterImage(specialSrc.get(), |
| 284 this->mapContext(ctx), | 284 this->mapContext(ctx), |
| 285 offset)); | 285 offset)); |
| 286 if (!tmp) { | 286 if (!tmp) { |
| 287 return false; | 287 return false; |
| 288 } | 288 } |
| 289 | 289 |
| 290 return tmp->internal_getBM(result); | 290 return tmp->internal_getBM(result); |
| 291 } | 291 } |
| 292 | 292 |
| 293 #ifdef SK_SUPPORT_LEGACY_FILTERBOUNDS_RETURN |
| 293 bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRec
t* dst, | 294 bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRec
t* dst, |
| 294 MapDirection direction) const { | 295 MapDirection direction) const { |
| 295 SkASSERT(dst); | 296 *dst = filterBounds(src, ctm, direction); |
| 296 SkIRect bounds; | 297 return true; |
| 298 } |
| 299 #endif |
| 300 |
| 301 SkIRect SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, |
| 302 MapDirection direction) const { |
| 297 if (kReverse_MapDirection == direction) { | 303 if (kReverse_MapDirection == direction) { |
| 298 this->onFilterNodeBounds(src, ctm, &bounds, direction); | 304 SkIRect bounds = this->onFilterNodeBounds(src, ctm, direction); |
| 299 return this->onFilterBounds(bounds, ctm, dst, direction); | 305 return this->onFilterBounds(bounds, ctm, direction); |
| 300 } else { | 306 } else { |
| 301 SkIRect temp; | 307 SkIRect bounds = this->onFilterBounds(src, ctm, direction); |
| 302 if (!this->onFilterBounds(src, ctm, &bounds, direction)) { | 308 bounds = this->onFilterNodeBounds(bounds, ctm, direction); |
| 303 return false; | 309 SkIRect dst; |
| 304 } | 310 this->getCropRect().applyTo(bounds, ctm, &dst); |
| 305 this->onFilterNodeBounds(bounds, ctm, &temp, direction); | 311 return dst; |
| 306 this->getCropRect().applyTo(temp, ctm, dst); | |
| 307 return true; | |
| 308 } | 312 } |
| 309 } | 313 } |
| 310 | 314 |
| 311 void SkImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { | 315 SkRect SkImageFilter::computeFastBounds(const SkRect& src) const { |
| 312 if (0 == fInputCount) { | 316 if (0 == fInputCount) { |
| 313 *dst = src; | 317 return src; |
| 314 return; | |
| 315 } | 318 } |
| 316 // We can't work directly on dst, since src and dst may alias. | 319 SkRect combinedBounds = this->getInput(0) ? this->getInput(0)->computeFastBo
unds(src) : src; |
| 317 SkRect combinedBounds; | |
| 318 if (this->getInput(0)) { | |
| 319 this->getInput(0)->computeFastBounds(src, &combinedBounds); | |
| 320 } else { | |
| 321 combinedBounds = src; | |
| 322 } | |
| 323 for (int i = 1; i < fInputCount; i++) { | 320 for (int i = 1; i < fInputCount; i++) { |
| 324 SkImageFilter* input = this->getInput(i); | 321 SkImageFilter* input = this->getInput(i); |
| 325 if (input) { | 322 if (input) { |
| 326 SkRect bounds; | 323 combinedBounds.join(input->computeFastBounds(src)); |
| 327 input->computeFastBounds(src, &bounds); | |
| 328 combinedBounds.join(bounds); | |
| 329 } else { | 324 } else { |
| 330 combinedBounds.join(src); | 325 combinedBounds.join(src); |
| 331 } | 326 } |
| 332 } | 327 } |
| 333 *dst = combinedBounds; | 328 return combinedBounds; |
| 334 } | 329 } |
| 335 | 330 |
| 336 bool SkImageFilter::canComputeFastBounds() const { | 331 bool SkImageFilter::canComputeFastBounds() const { |
| 337 for (int i = 0; i < fInputCount; i++) { | 332 for (int i = 0; i < fInputCount; i++) { |
| 338 SkImageFilter* input = this->getInput(i); | 333 SkImageFilter* input = this->getInput(i); |
| 339 if (input && !input->canComputeFastBounds()) { | 334 if (input && !input->canComputeFastBounds()) { |
| 340 return false; | 335 return false; |
| 341 } | 336 } |
| 342 } | 337 } |
| 343 return true; | 338 return true; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 } | 430 } |
| 436 if (nullptr != this->getInput(0) || (*filterPtr)->affectsTransparentBlack())
{ | 431 if (nullptr != this->getInput(0) || (*filterPtr)->affectsTransparentBlack())
{ |
| 437 (*filterPtr)->unref(); | 432 (*filterPtr)->unref(); |
| 438 return false; | 433 return false; |
| 439 } | 434 } |
| 440 return true; | 435 return true; |
| 441 } | 436 } |
| 442 | 437 |
| 443 bool SkImageFilter::applyCropRect(const Context& ctx, const SkIRect& srcBounds, | 438 bool SkImageFilter::applyCropRect(const Context& ctx, const SkIRect& srcBounds, |
| 444 SkIRect* dstBounds) const { | 439 SkIRect* dstBounds) const { |
| 445 this->onFilterNodeBounds(srcBounds, ctx.ctm(), dstBounds, kForward_MapDirect
ion); | 440 SkIRect temp = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_MapDi
rection); |
| 446 fCropRect.applyTo(*dstBounds, ctx.ctm(), dstBounds); | 441 fCropRect.applyTo(temp, ctx.ctm(), dstBounds); |
| 447 // Intersect against the clip bounds, in case the crop rect has | 442 // Intersect against the clip bounds, in case the crop rect has |
| 448 // grown the bounds beyond the original clip. This can happen for | 443 // grown the bounds beyond the original clip. This can happen for |
| 449 // example in tiling, where the clip is much smaller than the filtered | 444 // example in tiling, where the clip is much smaller than the filtered |
| 450 // primitive. If we didn't do this, we would be processing the filter | 445 // primitive. If we didn't do this, we would be processing the filter |
| 451 // at the full crop rect size in every tile. | 446 // at the full crop rect size in every tile. |
| 452 return dstBounds->intersect(ctx.clipBounds()); | 447 return dstBounds->intersect(ctx.clipBounds()); |
| 453 } | 448 } |
| 454 | 449 |
| 455 bool SkImageFilter::applyCropRectDeprecated(const Context& ctx, Proxy* proxy, co
nst SkBitmap& src, | 450 bool SkImageFilter::applyCropRectDeprecated(const Context& ctx, Proxy* proxy, co
nst SkBitmap& src, |
| 456 SkIPoint* srcOffset, SkIRect* bounds
, | 451 SkIPoint* srcOffset, SkIRect* bounds
, |
| 457 SkBitmap* dst) const { | 452 SkBitmap* dst) const { |
| 458 SkIRect srcBounds; | 453 SkIRect srcBounds; |
| 459 src.getBounds(&srcBounds); | 454 src.getBounds(&srcBounds); |
| 460 srcBounds.offset(*srcOffset); | 455 srcBounds.offset(*srcOffset); |
| 461 SkIRect dstBounds; | 456 SkIRect dstBounds = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_
MapDirection); |
| 462 this->onFilterNodeBounds(srcBounds, ctx.ctm(), &dstBounds, kForward_MapDirec
tion); | |
| 463 fCropRect.applyTo(dstBounds, ctx.ctm(), bounds); | 457 fCropRect.applyTo(dstBounds, ctx.ctm(), bounds); |
| 464 if (!bounds->intersect(ctx.clipBounds())) { | 458 if (!bounds->intersect(ctx.clipBounds())) { |
| 465 return false; | 459 return false; |
| 466 } | 460 } |
| 467 | 461 |
| 468 if (srcBounds.contains(*bounds)) { | 462 if (srcBounds.contains(*bounds)) { |
| 469 *dst = src; | 463 *dst = src; |
| 470 return true; | 464 return true; |
| 471 } else { | 465 } else { |
| 472 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), b
ounds->height())); | 466 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), b
ounds->height())); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 503 return surf->makeImageSnapshot(); | 497 return surf->makeImageSnapshot(); |
| 504 } | 498 } |
| 505 | 499 |
| 506 SkSpecialImage* SkImageFilter::applyCropRect(const Context& ctx, | 500 SkSpecialImage* SkImageFilter::applyCropRect(const Context& ctx, |
| 507 SkSpecialImage* src, | 501 SkSpecialImage* src, |
| 508 SkIPoint* srcOffset, | 502 SkIPoint* srcOffset, |
| 509 SkIRect* bounds) const { | 503 SkIRect* bounds) const { |
| 510 SkIRect srcBounds; | 504 SkIRect srcBounds; |
| 511 srcBounds = SkIRect::MakeXYWH(srcOffset->fX, srcOffset->fY, src->width(), sr
c->height()); | 505 srcBounds = SkIRect::MakeXYWH(srcOffset->fX, srcOffset->fY, src->width(), sr
c->height()); |
| 512 | 506 |
| 513 SkIRect dstBounds; | 507 SkIRect dstBounds = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_
MapDirection); |
| 514 this->onFilterNodeBounds(srcBounds, ctx.ctm(), &dstBounds, kForward_MapDirec
tion); | |
| 515 fCropRect.applyTo(dstBounds, ctx.ctm(), bounds); | 508 fCropRect.applyTo(dstBounds, ctx.ctm(), bounds); |
| 516 if (!bounds->intersect(ctx.clipBounds())) { | 509 if (!bounds->intersect(ctx.clipBounds())) { |
| 517 return nullptr; | 510 return nullptr; |
| 518 } | 511 } |
| 519 | 512 |
| 520 if (srcBounds.contains(*bounds)) { | 513 if (srcBounds.contains(*bounds)) { |
| 521 return SkRef(src); | 514 return SkRef(src); |
| 522 } else { | 515 } else { |
| 523 sk_sp<SkSpecialImage> img(pad_image(src, | 516 sk_sp<SkSpecialImage> img(pad_image(src, |
| 524 bounds->width(), bounds->height(), | 517 bounds->width(), bounds->height(), |
| 525 srcOffset->x() - bounds->x(), | 518 srcOffset->x() - bounds->x(), |
| 526 srcOffset->y() - bounds->y())); | 519 srcOffset->y() - bounds->y())); |
| 527 *srcOffset = SkIPoint::Make(bounds->x(), bounds->y()); | 520 *srcOffset = SkIPoint::Make(bounds->x(), bounds->y()); |
| 528 return img.release(); | 521 return img.release(); |
| 529 } | 522 } |
| 530 } | 523 } |
| 531 | 524 |
| 532 bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, | 525 SkIRect SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, |
| 533 SkIRect* dst, MapDirection direction) const { | 526 MapDirection direction) const { |
| 534 if (fInputCount < 1) { | 527 if (fInputCount < 1) { |
| 535 *dst = src; | 528 return src; |
| 536 return true; | |
| 537 } | 529 } |
| 538 | 530 |
| 539 SkIRect totalBounds; | 531 SkIRect totalBounds; |
| 540 for (int i = 0; i < fInputCount; ++i) { | 532 for (int i = 0; i < fInputCount; ++i) { |
| 541 SkImageFilter* filter = this->getInput(i); | 533 SkImageFilter* filter = this->getInput(i); |
| 542 SkIRect rect = src; | 534 SkIRect rect = filter ? filter->filterBounds(src, ctm, direction) : src; |
| 543 if (filter && !filter->filterBounds(src, ctm, &rect, direction)) { | |
| 544 return false; | |
| 545 } | |
| 546 if (0 == i) { | 535 if (0 == i) { |
| 547 totalBounds = rect; | 536 totalBounds = rect; |
| 548 } else { | 537 } else { |
| 549 totalBounds.join(rect); | 538 totalBounds.join(rect); |
| 550 } | 539 } |
| 551 } | 540 } |
| 552 | 541 |
| 553 // don't modify dst until now, so we don't accidentally change it in the | 542 return totalBounds; |
| 554 // loop, but then return false on the next filter. | |
| 555 *dst = totalBounds; | |
| 556 return true; | |
| 557 } | 543 } |
| 558 | 544 |
| 559 void SkImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix&, | 545 SkIRect SkImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix&, M
apDirection) const { |
| 560 SkIRect* dst, MapDirection) const { | 546 return src; |
| 561 *dst = src; | |
| 562 } | 547 } |
| 563 | 548 |
| 564 | 549 |
| 565 SkImageFilter::Context SkImageFilter::mapContext(const Context& ctx) const { | 550 SkImageFilter::Context SkImageFilter::mapContext(const Context& ctx) const { |
| 566 SkIRect clipBounds; | 551 SkIRect clipBounds = this->onFilterNodeBounds(ctx.clipBounds(), ctx.ctm(), |
| 567 this->onFilterNodeBounds(ctx.clipBounds(), ctx.ctm(), &clipBounds, | 552 MapDirection::kReverse_MapDire
ction); |
| 568 MapDirection::kReverse_MapDirection); | |
| 569 return Context(ctx.ctm(), clipBounds, ctx.cache()); | 553 return Context(ctx.ctm(), clipBounds, ctx.cache()); |
| 570 } | 554 } |
| 571 | 555 |
| 572 bool SkImageFilter::asFragmentProcessor(GrFragmentProcessor**, GrTexture*, | 556 bool SkImageFilter::asFragmentProcessor(GrFragmentProcessor**, GrTexture*, |
| 573 const SkMatrix&, const SkIRect&) const { | 557 const SkMatrix&, const SkIRect&) const { |
| 574 return false; | 558 return false; |
| 575 } | 559 } |
| 576 | 560 |
| 577 SkImageFilter* SkImageFilter::CreateMatrixFilter(const SkMatrix& matrix, | 561 SkImageFilter* SkImageFilter::CreateMatrixFilter(const SkMatrix& matrix, |
| 578 SkFilterQuality filterQuality, | 562 SkFilterQuality filterQuality, |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 } | 806 } |
| 823 return dev; | 807 return dev; |
| 824 } | 808 } |
| 825 | 809 |
| 826 bool SkImageFilter::DeviceProxy::filterImage(const SkImageFilter* filter, const
SkBitmap& src, | 810 bool SkImageFilter::DeviceProxy::filterImage(const SkImageFilter* filter, const
SkBitmap& src, |
| 827 const SkImageFilter::Context& ctx, | 811 const SkImageFilter::Context& ctx, |
| 828 SkBitmap* result, SkIPoint* offset) { | 812 SkBitmap* result, SkIPoint* offset) { |
| 829 return fDevice->filterImage(filter, src, ctx, result, offset); | 813 return fDevice->filterImage(filter, src, ctx, result, offset); |
| 830 } | 814 } |
| 831 | 815 |
| OLD | NEW |