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 |