Index: skia/ext/analysis_canvas.cc |
diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc |
index 2caa73d00dd2cbad35493532d6de1b9ade8cd84d..8ff2bf9f1a5b3ccc2ff164f0fb5fc146f1b85fb4 100644 |
--- a/skia/ext/analysis_canvas.cc |
+++ b/skia/ext/analysis_canvas.cc |
@@ -410,9 +410,103 @@ void AnalysisCanvas::onClipPath(const SkPath& path, |
INHERITED::onClipRect(path.getBounds(), op, edge_style); |
} |
+SkRect toDeviceSpace(const SkVector& scale, |
f(malita)
2016/10/25 13:26:25
SkMatrix::mapRectScaleTranslate()?
(see below)
|
+ const SkVector& translate, |
+ const SkRect& src) { |
+ SkRect result = SkRect::MakeLTRB(src.fLeft * scale.fX + translate.fX, |
+ src.fTop * scale.fY + translate.fY, |
+ src.fRight * scale.fX + translate.fX, |
+ src.fBottom * scale.fY + translate.fY); |
+ |
+ if (result.fLeft > result.fRight) |
+ std::swap(result.fLeft, result.fRight); |
+ |
+ if (result.fTop > result.fBottom) |
+ std::swap(result.fTop, result.fBottom); |
+ |
+ return result; |
+} |
+ |
+bool doesCoverCanvas(const SkRRect& rr, |
+ const SkMatrix& total_matrix, |
+ const SkIRect& clip_device_bounds) { |
+ // We cannot handle non axis aligned rectangles at the moment. |
+ if (!total_matrix.isScaleTranslate()) { |
+ return false; |
+ } |
+ |
+ const SkRect& bounding_rect = rr.rect(); |
+ |
+ // We inline the implementation of mapping and scaling to device space for |
+ // the fast path. We also inline here so that we can reuse intermediate |
+ // results for scaling multiple rects. |
+ float sx = total_matrix.getScaleX(); |
+ float sy = total_matrix.getScaleY(); |
+ float tx = total_matrix.getTranslateX(); |
+ float ty = total_matrix.getTranslateY(); |
+ |
+ SkVector scale = |
+ SkVector::Make(total_matrix.getScaleX(), total_matrix.getScaleY()); |
+ SkVector translate = SkVector::Make(total_matrix.getTranslateX(), |
+ total_matrix.getTranslateY()); |
+ |
+ const SkVector& ul_radii = rr.radii(SkRRect::kUpperLeft_Corner); |
+ const SkVector& ur_radii = rr.radii(SkRRect::kUpperRight_Corner); |
+ const SkVector& ll_radii = rr.radii(SkRRect::kLowerLeft_Corner); |
+ const SkVector& lr_radii = rr.radii(SkRRect::kLowerRight_Corner); |
+ |
+ SkRect ul_device_rect = |
+ toDeviceSpace(scale, translate, |
f(malita)
2016/10/25 13:26:25
total_matrix.mapRectScaleTranslate(&ul_device_rect
|
+ SkRect::MakeLTRB(bounding_rect.fLeft, bounding_rect.fTop, |
+ bounding_rect.fLeft + ul_radii.fX, |
+ bounding_rect.fTop + ul_radii.fY)); |
+ |
+ SkRect ur_device_rect = |
+ toDeviceSpace(scale, translate, |
f(malita)
2016/10/25 13:26:25
ditto
|
+ SkRect::MakeLTRB(bounding_rect.fRight - ur_radii.fX, |
+ bounding_rect.fTop, bounding_rect.fRight, |
+ bounding_rect.fTop + ur_radii.fY)); |
+ |
+ SkRect ll_device_rect = toDeviceSpace( |
f(malita)
2016/10/25 13:26:25
ditto
|
+ scale, translate, |
+ SkRect::MakeLTRB(bounding_rect.fLeft, bounding_rect.fBottom - ll_radii.fY, |
+ bounding_rect.fLeft + ll_radii.fX, |
+ bounding_rect.fBottom)); |
+ |
+ SkRect lr_device_rect = toDeviceSpace( |
f(malita)
2016/10/25 13:26:25
ditto
|
+ scale, translate, |
+ SkRect::MakeLTRB(bounding_rect.fRight - lr_radii.fX, |
+ bounding_rect.fBottom - lr_radii.fY, |
+ bounding_rect.fRight, bounding_rect.fBottom)); |
+ |
+ SkRect bounding_device_rect = toDeviceSpace(scale, translate, bounding_rect); |
f(malita)
2016/10/25 13:26:25
ditto
|
+ |
+ if (!bounding_device_rect.isFinite() || !ul_device_rect.isFinite() || |
+ !ur_device_rect.isFinite() || !ll_device_rect.isFinite() || |
+ !lr_device_rect.isFinite()) { |
+ return false; |
+ } |
+ |
+ SkRect clip_device_rect = SkRect::MakeFromIRect(clip_device_bounds); |
+ |
+ return bounding_device_rect.contains(clip_device_rect) && |
+ !SkRect::Intersects(ul_device_rect, clip_device_rect) && |
+ !SkRect::Intersects(ur_device_rect, clip_device_rect) && |
+ !SkRect::Intersects(ll_device_rect, clip_device_rect) && |
+ !SkRect::Intersects(lr_device_rect, clip_device_rect); |
f(malita)
2016/10/25 13:26:25
Not quite the same thing, but wouldn't it be suffi
|
+} |
+ |
void AnalysisCanvas::onClipRRect(const SkRRect& rrect, |
SkRegion::Op op, |
ClipEdgeStyle edge_style) { |
+ SkIRect clip_device_bounds; |
+ if (getClipDeviceBounds(&clip_device_bounds) && |
+ doesCoverCanvas(rrect, getTotalMatrix(), clip_device_bounds)) { |
+ // If the canvas is fully contained within the clip, it is as if we weren't |
+ // clipped at all, so bail early. |
+ return; |
+ } |
+ |
OnComplexClip(); |
INHERITED::onClipRect(rrect.getBounds(), op, edge_style); |
} |