Add secret draw-behind method
This is a variant of drawPaint but is automatically clipped
to the bounds of the most recent saveBehind buffer (axis-aligned bounds).
No public exposure.
Impl is pretty simple (its a variant of drawPaint)
- find the most recent saveBehind device bounds
- if there is none, draw nothing, else
- temporarily intersect the device's clip with that bounds
- drawPaint
- restore the clip
See https://buganizer.corp.google.com/issues/129117085
Change-Id: I7c532e63a80b118fb2416c572b8e0d2abf8cf59a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/209166
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 0fddd6b..a0c956b 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1710,6 +1710,11 @@
this->onDrawRect(r.makeSorted(), paint);
}
+void SkCanvas::drawClippedToSaveBehind(const SkPaint& paint) {
+ TRACE_EVENT0("skia", TRACE_FUNC);
+ this->onDrawBehind(paint);
+}
+
void SkCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
TRACE_EVENT0("skia", TRACE_FUNC);
if (region.isEmpty()) {
@@ -2120,6 +2125,41 @@
LOOPER_END
}
+void SkCanvas::onDrawBehind(const SkPaint& paint) {
+ SkIRect bounds;
+ SkDeque::Iter iter(fMCStack, SkDeque::Iter::kBack_IterStart);
+ for (;;) {
+ const MCRec* rec = (const MCRec*)iter.prev();
+ if (!rec) {
+ return; // no backimages, so nothing to draw
+ }
+ if (rec->fBackImage) {
+ bounds = SkIRect::MakeXYWH(rec->fBackImage->fLoc.fX, rec->fBackImage->fLoc.fY,
+ rec->fBackImage->fImage->width(),
+ rec->fBackImage->fImage->height());
+ break;
+ }
+ }
+
+ LOOPER_BEGIN(paint, nullptr)
+
+ while (iter.next()) {
+ SkBaseDevice* dev = iter.fDevice;
+
+ SkMatrix ctm = dev->ctm();
+ dev->save();
+ // We use clipRegion because it is already defined to operate in dev-space
+ // (i.e. ignores the ctm). However, it is going to first translate by -origin,
+ // but we don't want that, so we undo that before calling in.
+ SkRegion rgn(bounds.makeOffset(dev->fOrigin.fX, dev->fOrigin.fY));
+ dev->clipRegion(rgn, SkClipOp::kIntersect);
+ dev->drawPaint(looper.paint());
+ dev->restore(ctm);
+ }
+
+ LOOPER_END
+}
+
void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
SkASSERT(oval.isSorted());
if (paint.canComputeFastBounds()) {