diff options
author | Robert Phillips <robertphillips@google.com> | 2018-05-17 11:17:39 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-05-17 17:06:24 +0000 |
commit | 120784394c160d009bc3aa88dd217c13c105a6ca (patch) | |
tree | c2f3406ff37360a511af362138938e754c057619 /src/core/SkCanvas.cpp | |
parent | ffb3d688b0e76ad7d1517657b00e4525cc603f40 (diff) |
Fix srcBounds computation in SkMatrixConvolutionImageFilter
Note that this does change the behavior of the cropRect for the repeated case. The cropRect now only acts as a hard clip on the output.
BUG= skia:7766
Change-Id: I1d66678bc797cd4835701cd20c36e68b22ac880a
Reviewed-on: https://skia-review.googlesource.com/127338
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'src/core/SkCanvas.cpp')
-rw-r--r-- | src/core/SkCanvas.cpp | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index a467cac060..00bbdf418e 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -879,24 +879,42 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlag const SkMatrix& ctm = fMCRec->fMatrix; // this->getTotalMatrix() - if (imageFilter) { - clipBounds = imageFilter->filterBounds(clipBounds, ctm, - SkImageFilter::kReverse_MapDirection); - if (bounds && !imageFilter->canComputeFastBounds()) { - bounds = nullptr; - } + if (imageFilter && bounds && !imageFilter->canComputeFastBounds()) { + // If the image filter DAG affects transparent black then we will need to render + // out to the clip bounds + bounds = nullptr; } - SkIRect ir; + + SkIRect inputSaveLayerBounds; if (bounds) { SkRect r; ctm.mapRect(&r, *bounds); - r.roundOut(&ir); + r.roundOut(&inputSaveLayerBounds); } else { // no user bounds, so just use the clip - ir = clipBounds; + inputSaveLayerBounds = clipBounds; + } + + if (imageFilter) { + // expand the clip bounds by the image filter DAG to include extra content that might + // be required by the image filters. + clipBounds = imageFilter->filterBounds(clipBounds, ctm, + SkImageFilter::kReverse_MapDirection, + &inputSaveLayerBounds); + } + + SkIRect clippedSaveLayerBounds; + if (bounds) { + // For better or for worse, user bounds currently act as a hard clip on the layer's + // extent (i.e., they implement the CSS filter-effects 'filter region' feature). + clippedSaveLayerBounds = inputSaveLayerBounds; + } else { + // If there are no user bounds, we don't want to artificially restrict the resulting + // layer bounds, so allow the expanded clip bounds free reign. + clippedSaveLayerBounds = clipBounds; } // early exit if the layer's bounds are clipped out - if (!ir.intersect(clipBounds)) { + if (!clippedSaveLayerBounds.intersect(clipBounds)) { if (BoundsAffectsClip(saveLayerFlags)) { fMCRec->fTopLayer->fDevice->clipRegion(SkRegion(), SkClipOp::kIntersect); // empty fMCRec->fRasterClip.setEmpty(); @@ -904,17 +922,18 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlag } return false; } - SkASSERT(!ir.isEmpty()); + SkASSERT(!clippedSaveLayerBounds.isEmpty()); if (BoundsAffectsClip(saveLayerFlags)) { // Simplify the current clips since they will be applied properly during restore() - fMCRec->fRasterClip.setRect(ir); - fDeviceClipBounds = qr_clip_bounds(ir); + fMCRec->fRasterClip.setRect(clippedSaveLayerBounds); + fDeviceClipBounds = qr_clip_bounds(clippedSaveLayerBounds); } if (intersection) { - *intersection = ir; + *intersection = clippedSaveLayerBounds; } + return true; } |