aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/effects/SkMergeImageFilter.cpp
diff options
context:
space:
mode:
authorGravatar senorblanco <senorblanco@chromium.org>2015-11-25 07:06:55 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-11-25 07:06:55 -0800
commit4a24398391536f7b176b44a8c45dc288655b4adb (patch)
treef2c1746d6025b9c074cc659e9c643fe627203fe1 /src/effects/SkMergeImageFilter.cpp
parent43432f333ab82f5d272c8564802e4ba1483e9f45 (diff)
Fix SkMergeImageFilter crop rect computation.
The crop rect should be applied to the union of the input bounds, not to the src input's bounds. These are often the same, since the saveLayer offscreen size is computed as the union of all the required bounds, but is not correct if the input primitive is not used (e.g., if all inputs are connected to SkImageSources). But this will change as we move to more accurate intermediate bounds computations (getting rid of the join() hacks as described in skbug.com/3194). Since we can't know this without actually processing the inputs, split SkMergeImageFilter processing into: - filter all inputs - applyCropRect to the union'ed bounds - allocate the destination - do the merge BUG=3194 Review URL: https://codereview.chromium.org/1475793002
Diffstat (limited to 'src/effects/SkMergeImageFilter.cpp')
-rwxr-xr-xsrc/effects/SkMergeImageFilter.cpp60
1 files changed, 39 insertions, 21 deletions
diff --git a/src/effects/SkMergeImageFilter.cpp b/src/effects/SkMergeImageFilter.cpp
index d6f0eaa794..2ae8b35cd0 100755
--- a/src/effects/SkMergeImageFilter.cpp
+++ b/src/effects/SkMergeImageFilter.cpp
@@ -15,7 +15,7 @@
///////////////////////////////////////////////////////////////////////////////
void SkMergeImageFilter::initAllocModes() {
- int inputCount = countInputs();
+ int inputCount = this->countInputs();
if (inputCount) {
size_t size = sizeof(uint8_t) * inputCount;
if (size <= sizeof(fStorage)) {
@@ -31,7 +31,7 @@ void SkMergeImageFilter::initAllocModes() {
void SkMergeImageFilter::initModes(const SkXfermode::Mode modes[]) {
if (modes) {
this->initAllocModes();
- int inputCount = countInputs();
+ int inputCount = this->countInputs();
for (int i = 0; i < inputCount; ++i) {
fModes[i] = SkToU8(modes[i]);
}
@@ -58,46 +58,64 @@ SkMergeImageFilter::~SkMergeImageFilter() {
bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
const Context& ctx,
SkBitmap* result, SkIPoint* offset) const {
- if (countInputs() < 1) {
+ int inputCount = this->countInputs();
+ if (inputCount < 1) {
return false;
}
SkIRect bounds;
- if (!this->applyCropRect(ctx, src, SkIPoint::Make(0, 0), &bounds)) {
+
+ SkAutoTDeleteArray<SkBitmap> inputs(new SkBitmap[inputCount]);
+ SkAutoTDeleteArray<SkIPoint> offsets(new SkIPoint[inputCount]);
+ bool didProduceResult = false;
+
+ // Filter all of the inputs.
+ for (int i = 0; i < inputCount; ++i) {
+ inputs[i] = src;
+ offsets[i].setZero();
+ if (!this->filterInput(i, proxy, src, ctx, &inputs[i], &offsets[i])) {
+ inputs[i].reset();
+ continue;
+ }
+ SkIRect srcBounds;
+ inputs[i].getBounds(&srcBounds);
+ srcBounds.offset(offsets[i]);
+ if (!didProduceResult) {
+ bounds = srcBounds;
+ didProduceResult = true;
+ } else {
+ bounds.join(srcBounds);
+ }
+ }
+ if (!didProduceResult) {
+ return false;
+ }
+
+ // Apply the crop rect to the union of the inputs' bounds.
+ if (!this->getCropRect().applyTo(bounds, ctx, &bounds)) {
return false;
}
const int x0 = bounds.left();
const int y0 = bounds.top();
+ // Allocate the destination buffer.
SkAutoTUnref<SkBaseDevice> dst(proxy->createDevice(bounds.width(), bounds.height()));
if (nullptr == dst) {
return false;
}
SkCanvas canvas(dst);
- SkPaint paint;
- bool didProduceResult = false;
- int inputCount = countInputs();
+ // Composite all of the filter inputs.
for (int i = 0; i < inputCount; ++i) {
- SkBitmap tmp;
- SkBitmap input = src;
- SkIPoint pos = SkIPoint::Make(0, 0);
- if (!this->filterInput(i, proxy, src, ctx, &input, &pos)) {
- continue;
- }
+ SkPaint paint;
if (fModes) {
paint.setXfermodeMode((SkXfermode::Mode)fModes[i]);
- } else {
- paint.setXfermode(nullptr);
}
- canvas.drawBitmap(input, SkIntToScalar(pos.x() - x0), SkIntToScalar(pos.y() - y0), &paint);
- didProduceResult = true;
+ canvas.drawBitmap(inputs[i], SkIntToScalar(offsets[i].x() - x0),
+ SkIntToScalar(offsets[i].y() - y0), &paint);
}
- if (!didProduceResult)
- return false;
-
offset->fX = bounds.left();
offset->fY = bounds.top();
*result = dst->accessBitmap(false);
@@ -134,7 +152,7 @@ void SkMergeImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeBool(fModes != nullptr);
if (fModes) {
- buffer.writeByteArray(fModes, countInputs() * sizeof(fModes[0]));
+ buffer.writeByteArray(fModes, this->countInputs() * sizeof(fModes[0]));
}
}