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 |