| 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 str->appendf("%.2f", fRect.height()); | 62 str->appendf("%.2f", fRect.height()); |
| 63 } else { | 63 } else { |
| 64 str->appendf("X"); | 64 str->appendf("X"); |
| 65 } | 65 } |
| 66 str->appendf(") "); | 66 str->appendf(") "); |
| 67 } | 67 } |
| 68 #endif | 68 #endif |
| 69 | 69 |
| 70 void SkImageFilter::CropRect::applyTo(const SkIRect& imageBounds, | 70 void SkImageFilter::CropRect::applyTo(const SkIRect& imageBounds, |
| 71 const SkMatrix& ctm, | 71 const SkMatrix& ctm, |
| 72 bool embiggen, |
| 72 SkIRect* cropped) const { | 73 SkIRect* cropped) const { |
| 73 *cropped = imageBounds; | 74 *cropped = imageBounds; |
| 74 if (fFlags) { | 75 if (fFlags) { |
| 75 SkRect devCropR; | 76 SkRect devCropR; |
| 76 ctm.mapRect(&devCropR, fRect); | 77 ctm.mapRect(&devCropR, fRect); |
| 77 const SkIRect devICropR = devCropR.roundOut(); | 78 SkIRect devICropR = devCropR.roundOut(); |
| 78 | 79 |
| 79 // Compute the left/top first, in case we have to read them to compute r
ight/bottom | 80 // Compute the left/top first, in case we need to modify the right/botto
m for a missing edge |
| 80 if (fFlags & kHasLeft_CropEdge) { | 81 if (fFlags & kHasLeft_CropEdge) { |
| 81 cropped->fLeft = devICropR.fLeft; | 82 if (embiggen || devICropR.fLeft > cropped->fLeft) { |
| 83 cropped->fLeft = devICropR.fLeft; |
| 84 } |
| 85 } else { |
| 86 devICropR.fRight = cropped->fLeft + devICropR.width(); |
| 82 } | 87 } |
| 83 if (fFlags & kHasTop_CropEdge) { | 88 if (fFlags & kHasTop_CropEdge) { |
| 84 cropped->fTop = devICropR.fTop; | 89 if (embiggen || devICropR.fTop > cropped->fTop) { |
| 90 cropped->fTop = devICropR.fTop; |
| 91 } |
| 92 } else { |
| 93 devICropR.fBottom = cropped->fTop + devICropR.height(); |
| 85 } | 94 } |
| 86 if (fFlags & kHasWidth_CropEdge) { | 95 if (fFlags & kHasWidth_CropEdge) { |
| 87 cropped->fRight = cropped->fLeft + devICropR.width(); | 96 if (embiggen || devICropR.fRight < cropped->fRight) { |
| 97 cropped->fRight = devICropR.fRight; |
| 98 } |
| 88 } | 99 } |
| 89 if (fFlags & kHasHeight_CropEdge) { | 100 if (fFlags & kHasHeight_CropEdge) { |
| 90 cropped->fBottom = cropped->fTop + devICropR.height(); | 101 if (embiggen || devICropR.fBottom < cropped->fBottom) { |
| 102 cropped->fBottom = devICropR.fBottom; |
| 103 } |
| 91 } | 104 } |
| 92 } | 105 } |
| 93 } | 106 } |
| 94 | 107 |
| 95 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 108 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 96 | 109 |
| 97 static int32_t next_image_filter_unique_id() { | 110 static int32_t next_image_filter_unique_id() { |
| 98 static int32_t gImageFilterUniqueID; | 111 static int32_t gImageFilterUniqueID; |
| 99 | 112 |
| 100 // Never return 0. | 113 // Never return 0. |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 | 312 |
| 300 SkIRect SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, | 313 SkIRect SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, |
| 301 MapDirection direction) const { | 314 MapDirection direction) const { |
| 302 if (kReverse_MapDirection == direction) { | 315 if (kReverse_MapDirection == direction) { |
| 303 SkIRect bounds = this->onFilterNodeBounds(src, ctm, direction); | 316 SkIRect bounds = this->onFilterNodeBounds(src, ctm, direction); |
| 304 return this->onFilterBounds(bounds, ctm, direction); | 317 return this->onFilterBounds(bounds, ctm, direction); |
| 305 } else { | 318 } else { |
| 306 SkIRect bounds = this->onFilterBounds(src, ctm, direction); | 319 SkIRect bounds = this->onFilterBounds(src, ctm, direction); |
| 307 bounds = this->onFilterNodeBounds(bounds, ctm, direction); | 320 bounds = this->onFilterNodeBounds(bounds, ctm, direction); |
| 308 SkIRect dst; | 321 SkIRect dst; |
| 309 this->getCropRect().applyTo(bounds, ctm, &dst); | 322 this->getCropRect().applyTo(bounds, ctm, this->affectsTransparentBlack()
, &dst); |
| 310 return dst; | 323 return dst; |
| 311 } | 324 } |
| 312 } | 325 } |
| 313 | 326 |
| 314 SkRect SkImageFilter::computeFastBounds(const SkRect& src) const { | 327 SkRect SkImageFilter::computeFastBounds(const SkRect& src) const { |
| 315 if (0 == fInputCount) { | 328 if (0 == fInputCount) { |
| 316 return src; | 329 return src; |
| 317 } | 330 } |
| 318 SkRect combinedBounds = this->getInput(0) ? this->getInput(0)->computeFastBo
unds(src) : src; | 331 SkRect combinedBounds = this->getInput(0) ? this->getInput(0)->computeFastBo
unds(src) : src; |
| 319 for (int i = 1; i < fInputCount; i++) { | 332 for (int i = 1; i < fInputCount; i++) { |
| 320 SkImageFilter* input = this->getInput(i); | 333 SkImageFilter* input = this->getInput(i); |
| 321 if (input) { | 334 if (input) { |
| 322 combinedBounds.join(input->computeFastBounds(src)); | 335 combinedBounds.join(input->computeFastBounds(src)); |
| 323 } else { | 336 } else { |
| 324 combinedBounds.join(src); | 337 combinedBounds.join(src); |
| 325 } | 338 } |
| 326 } | 339 } |
| 327 return combinedBounds; | 340 return combinedBounds; |
| 328 } | 341 } |
| 329 | 342 |
| 330 bool SkImageFilter::canComputeFastBounds() const { | 343 bool SkImageFilter::canComputeFastBounds() const { |
| 344 if (this->affectsTransparentBlack()) { |
| 345 return false; |
| 346 } |
| 331 for (int i = 0; i < fInputCount; i++) { | 347 for (int i = 0; i < fInputCount; i++) { |
| 332 SkImageFilter* input = this->getInput(i); | 348 SkImageFilter* input = this->getInput(i); |
| 333 if (input && !input->canComputeFastBounds()) { | 349 if (input && !input->canComputeFastBounds()) { |
| 334 return false; | 350 return false; |
| 335 } | 351 } |
| 336 } | 352 } |
| 337 return true; | 353 return true; |
| 338 } | 354 } |
| 339 | 355 |
| 340 bool SkImageFilter::onFilterImageDeprecated(Proxy*, const SkBitmap&, const Conte
xt&, | 356 bool SkImageFilter::onFilterImageDeprecated(Proxy*, const SkBitmap&, const Conte
xt&, |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 if (nullptr != this->getInput(0) || (*filterPtr)->affectsTransparentBlack())
{ | 446 if (nullptr != this->getInput(0) || (*filterPtr)->affectsTransparentBlack())
{ |
| 431 (*filterPtr)->unref(); | 447 (*filterPtr)->unref(); |
| 432 return false; | 448 return false; |
| 433 } | 449 } |
| 434 return true; | 450 return true; |
| 435 } | 451 } |
| 436 | 452 |
| 437 bool SkImageFilter::applyCropRect(const Context& ctx, const SkIRect& srcBounds, | 453 bool SkImageFilter::applyCropRect(const Context& ctx, const SkIRect& srcBounds, |
| 438 SkIRect* dstBounds) const { | 454 SkIRect* dstBounds) const { |
| 439 SkIRect temp = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_MapDi
rection); | 455 SkIRect temp = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_MapDi
rection); |
| 440 fCropRect.applyTo(temp, ctx.ctm(), dstBounds); | 456 fCropRect.applyTo(temp, ctx.ctm(), this->affectsTransparentBlack(), dstBound
s); |
| 441 // Intersect against the clip bounds, in case the crop rect has | 457 // Intersect against the clip bounds, in case the crop rect has |
| 442 // grown the bounds beyond the original clip. This can happen for | 458 // grown the bounds beyond the original clip. This can happen for |
| 443 // example in tiling, where the clip is much smaller than the filtered | 459 // example in tiling, where the clip is much smaller than the filtered |
| 444 // primitive. If we didn't do this, we would be processing the filter | 460 // primitive. If we didn't do this, we would be processing the filter |
| 445 // at the full crop rect size in every tile. | 461 // at the full crop rect size in every tile. |
| 446 return dstBounds->intersect(ctx.clipBounds()); | 462 return dstBounds->intersect(ctx.clipBounds()); |
| 447 } | 463 } |
| 448 | 464 |
| 449 bool SkImageFilter::applyCropRectDeprecated(const Context& ctx, Proxy* proxy, co
nst SkBitmap& src, | 465 bool SkImageFilter::applyCropRectDeprecated(const Context& ctx, Proxy* proxy, co
nst SkBitmap& src, |
| 450 SkIPoint* srcOffset, SkIRect* bounds
, | 466 SkIPoint* srcOffset, SkIRect* bounds
, |
| 451 SkBitmap* dst) const { | 467 SkBitmap* dst) const { |
| 452 SkIRect srcBounds; | 468 SkIRect srcBounds; |
| 453 src.getBounds(&srcBounds); | 469 src.getBounds(&srcBounds); |
| 454 srcBounds.offset(*srcOffset); | 470 srcBounds.offset(*srcOffset); |
| 455 SkIRect dstBounds = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_
MapDirection); | 471 SkIRect dstBounds = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_
MapDirection); |
| 456 fCropRect.applyTo(dstBounds, ctx.ctm(), bounds); | 472 fCropRect.applyTo(dstBounds, ctx.ctm(), this->affectsTransparentBlack(), bou
nds); |
| 457 if (!bounds->intersect(ctx.clipBounds())) { | 473 if (!bounds->intersect(ctx.clipBounds())) { |
| 458 return false; | 474 return false; |
| 459 } | 475 } |
| 460 | 476 |
| 461 if (srcBounds.contains(*bounds)) { | 477 if (srcBounds.contains(*bounds)) { |
| 462 *dst = src; | 478 *dst = src; |
| 463 return true; | 479 return true; |
| 464 } else { | 480 } else { |
| 465 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), b
ounds->height())); | 481 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), b
ounds->height())); |
| 466 if (!device) { | 482 if (!device) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 497 } | 513 } |
| 498 | 514 |
| 499 sk_sp<SkSpecialImage> SkImageFilter::applyCropRect(const Context& ctx, | 515 sk_sp<SkSpecialImage> SkImageFilter::applyCropRect(const Context& ctx, |
| 500 SkSpecialImage* src, | 516 SkSpecialImage* src, |
| 501 SkIPoint* srcOffset, | 517 SkIPoint* srcOffset, |
| 502 SkIRect* bounds) const { | 518 SkIRect* bounds) const { |
| 503 SkIRect srcBounds; | 519 SkIRect srcBounds; |
| 504 srcBounds = SkIRect::MakeXYWH(srcOffset->fX, srcOffset->fY, src->width(), sr
c->height()); | 520 srcBounds = SkIRect::MakeXYWH(srcOffset->fX, srcOffset->fY, src->width(), sr
c->height()); |
| 505 | 521 |
| 506 SkIRect dstBounds = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_
MapDirection); | 522 SkIRect dstBounds = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_
MapDirection); |
| 507 fCropRect.applyTo(dstBounds, ctx.ctm(), bounds); | 523 fCropRect.applyTo(dstBounds, ctx.ctm(), this->affectsTransparentBlack(), bou
nds); |
| 508 if (!bounds->intersect(ctx.clipBounds())) { | 524 if (!bounds->intersect(ctx.clipBounds())) { |
| 509 return nullptr; | 525 return nullptr; |
| 510 } | 526 } |
| 511 | 527 |
| 512 if (srcBounds.contains(*bounds)) { | 528 if (srcBounds.contains(*bounds)) { |
| 513 return sk_sp<SkSpecialImage>(SkRef(src)); | 529 return sk_sp<SkSpecialImage>(SkRef(src)); |
| 514 } else { | 530 } else { |
| 515 sk_sp<SkSpecialImage> img(pad_image(src, | 531 sk_sp<SkSpecialImage> img(pad_image(src, |
| 516 bounds->width(), bounds->height(), | 532 bounds->width(), bounds->height(), |
| 517 srcOffset->x() - bounds->x(), | 533 srcOffset->x() - bounds->x(), |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 805 dev = SkBitmapDevice::Create(cinfo.fInfo, surfaceProps); | 821 dev = SkBitmapDevice::Create(cinfo.fInfo, surfaceProps); |
| 806 } | 822 } |
| 807 return dev; | 823 return dev; |
| 808 } | 824 } |
| 809 | 825 |
| 810 bool SkImageFilter::DeviceProxy::filterImage(const SkImageFilter* filter, const
SkBitmap& src, | 826 bool SkImageFilter::DeviceProxy::filterImage(const SkImageFilter* filter, const
SkBitmap& src, |
| 811 const SkImageFilter::Context& ctx, | 827 const SkImageFilter::Context& ctx, |
| 812 SkBitmap* result, SkIPoint* offset) { | 828 SkBitmap* result, SkIPoint* offset) { |
| 813 return fDevice->filterImage(filter, src, ctx, result, offset); | 829 return fDevice->filterImage(filter, src, ctx, result, offset); |
| 814 } | 830 } |
| OLD | NEW |