From c2c66f09f6e5c2b545e47dea08c7c56198c66a20 Mon Sep 17 00:00:00 2001 From: Mike Reed Date: Wed, 1 May 2019 11:43:22 -0400 Subject: 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 Reviewed-by: Brian Salomon Reviewed-on: https://skia-review.googlesource.com/c/skia/+/211600 Commit-Queue: Derek Sollenberger Reviewed-by: Derek Sollenberger --- gm/savelayer.cpp | 33 +++++++++++++++++++--------- include/core/SkCanvas.h | 7 ++++++ include/core/SkCanvasVirtualEnforcer.h | 1 + include/core/SkOverdrawCanvas.h | 1 + include/utils/SkNWayCanvas.h | 1 + include/utils/SkNoDrawCanvas.h | 1 + include/utils/SkPaintFilterCanvas.h | 1 + src/core/SkCanvas.cpp | 40 ++++++++++++++++++++++++++++++++++ src/core/SkCanvasPriv.h | 10 +++++++++ src/core/SkLiteDL.cpp | 11 +++++++++- src/core/SkLiteDL.h | 1 + src/core/SkLiteRecorder.cpp | 3 +++ src/core/SkLiteRecorder.h | 1 + src/core/SkOverdrawCanvas.cpp | 4 ++++ src/core/SkPictureFlat.h | 4 +++- src/core/SkPicturePlayback.cpp | 8 +++++++ src/core/SkPictureRecord.cpp | 9 ++++++++ src/core/SkPictureRecord.h | 1 + src/core/SkRecordDraw.cpp | 5 +++++ src/core/SkRecorder.cpp | 4 ++++ src/core/SkRecorder.h | 1 + src/core/SkRecords.h | 3 +++ src/utils/SkNWayCanvas.cpp | 7 ++++++ src/utils/SkPaintFilterCanvas.cpp | 7 ++++++ tools/debugger/SkDebugCanvas.cpp | 4 ++++ tools/debugger/SkDebugCanvas.h | 1 + tools/debugger/SkDrawCommand.cpp | 22 +++++++++++++++++++ tools/debugger/SkDrawCommand.h | 13 +++++++++++ 28 files changed, 192 insertions(+), 12 deletions(-) diff --git a/gm/savelayer.cpp b/gm/savelayer.cpp index d6a33b2d96..1347cbc8cd 100644 --- a/gm/savelayer.cpp +++ b/gm/savelayer.cpp @@ -281,7 +281,8 @@ DEF_SIMPLE_GM(savelayer_coverage, canvas, 500, 500) { #include "SkGradientShader.h" #include "SkTextBlob.h" -static void draw_cell(SkCanvas* canvas, sk_sp blob, SkColor c, SkScalar w, SkScalar h) { +static void draw_cell(SkCanvas* canvas, sk_sp blob, SkColor c, SkScalar w, SkScalar h, + bool useDrawBehind) { SkRect r = SkRect::MakeWH(w, h); SkPaint p; p.setColor(c); @@ -309,7 +310,12 @@ static void draw_cell(SkCanvas* canvas, sk_sp blob, SkColor c, SkSca auto sh = SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::kClamp_TileMode); p.setShader(sh); p.setBlendMode(SkBlendMode::kDstIn); - canvas->drawRect(r, p); + + if (useDrawBehind) { + SkCanvasPriv::DrawBehind(canvas, p); + } else { + canvas->drawRect(r, p); + } // this should restore the behind image canvas->restore(); @@ -320,10 +326,9 @@ static void draw_cell(SkCanvas* canvas, sk_sp blob, SkColor c, SkSca p.reset(); p.setStyle(SkPaint::kStroke_Style); p.setAlphaf(0.25f); - canvas->drawRect(r, p); } -static void draw_list(SkCanvas* canvas, sk_sp blob) { +static void draw_list(SkCanvas* canvas, sk_sp blob, bool useDrawBehind) { SkAutoCanvasRestore acr(canvas, true); SkRandom rand; @@ -332,19 +337,27 @@ static void draw_list(SkCanvas* canvas, sk_sp blob) { for (int i = 0; i < 8; ++i) { SkColor c = rand.nextU(); // ensure we're opaque c = (c & 0xFFFFFF) | 0x80000000; - draw_cell(canvas, blob, c, w, h); + draw_cell(canvas, blob, c, w, h, useDrawBehind); canvas->translate(0, h); } } -DEF_SIMPLE_GM(save_behind, canvas, 400, 670) { +DEF_SIMPLE_GM(save_behind, canvas, 830, 670) { SkFont font; font.setSize(30); const char text[] = "This is a very long line of text"; auto blob = SkTextBlob::MakeFromText(text, strlen(text), font); - draw_list(canvas, blob); - canvas->translate(0, 350); - canvas->saveLayer({0, 0, 400, 320}, nullptr); - draw_list(canvas, blob); + for (bool useDrawBehind : {false, true}) { + canvas->save(); + + draw_list(canvas, blob, useDrawBehind); + canvas->translate(0, 350); + canvas->saveLayer({0, 0, 400, 320}, nullptr); + draw_list(canvas, blob, useDrawBehind); + canvas->restore(); + + canvas->restore(); + canvas->translate(430, 0); + } } diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index 397939b32b..40f16010b1 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -2379,6 +2379,7 @@ protected: // SkCanvasVirtualEnforcer (in SkCanvasVirtualEnforcer.h). This ensures that subclasses using // that mechanism will be required to implement the new function. virtual void onDrawPaint(const SkPaint& paint); + virtual void onDrawBehind(const SkPaint& paint); virtual void onDrawRect(const SkRect& rect, const SkPaint& paint); virtual void onDrawEdgeAARect(const SkRect& rect, QuadAAFlags edgeAA, SkColor color, SkBlendMode mode); @@ -2587,6 +2588,12 @@ private: */ int only_axis_aligned_saveBehind(const SkRect* subset); + /** + * Like drawPaint, but magically clipped to the most recent saveBehind buffer rectangle. + * If there is no active saveBehind, then this draws nothing. + */ + void drawClippedToSaveBehind(const SkPaint&); + void resetForNextPicture(const SkIRect& bounds); // needs gettotalclip() diff --git a/include/core/SkCanvasVirtualEnforcer.h b/include/core/SkCanvasVirtualEnforcer.h index f097911b1c..3a5dac3af3 100644 --- a/include/core/SkCanvasVirtualEnforcer.h +++ b/include/core/SkCanvasVirtualEnforcer.h @@ -20,6 +20,7 @@ public: protected: void onDrawPaint(const SkPaint& paint) override = 0; + void onDrawBehind(const SkPaint&) override {} // make zero after android updates void onDrawRect(const SkRect& rect, const SkPaint& paint) override = 0; void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override = 0; void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, diff --git a/include/core/SkOverdrawCanvas.h b/include/core/SkOverdrawCanvas.h index e0d05c82bd..c75d7ae369 100644 --- a/include/core/SkOverdrawCanvas.h +++ b/include/core/SkOverdrawCanvas.h @@ -25,6 +25,7 @@ public: void onDrawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode, const SkPaint&) override; void onDrawPaint(const SkPaint&) override; + void onDrawBehind(const SkPaint& paint) override; void onDrawRect(const SkRect&, const SkPaint&) override; void onDrawEdgeAARect(const SkRect&, SkCanvas::QuadAAFlags, SkColor, SkBlendMode) override; void onDrawRegion(const SkRegion&, const SkPaint&) override; diff --git a/include/utils/SkNWayCanvas.h b/include/utils/SkNWayCanvas.h index 09b071d5c7..de9f44bf09 100644 --- a/include/utils/SkNWayCanvas.h +++ b/include/utils/SkNWayCanvas.h @@ -41,6 +41,7 @@ protected: const SkPaint& paint) override; void onDrawPaint(const SkPaint&) override; + void onDrawBehind(const SkPaint&) override; void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override; void onDrawRect(const SkRect&, const SkPaint&) override; void onDrawEdgeAARect(const SkRect&, SkCanvas::QuadAAFlags, SkColor, SkBlendMode) override; diff --git a/include/utils/SkNoDrawCanvas.h b/include/utils/SkNoDrawCanvas.h index ff1b027548..43b49bcf7f 100644 --- a/include/utils/SkNoDrawCanvas.h +++ b/include/utils/SkNoDrawCanvas.h @@ -49,6 +49,7 @@ protected: const SkPaint&) override {} void onDrawPaint(const SkPaint&) override {} + void onDrawBehind(const SkPaint&) override {} void onDrawPoints(PointMode, size_t, const SkPoint[], const SkPaint&) override {} void onDrawRect(const SkRect&, const SkPaint&) override {} void onDrawEdgeAARect(const SkRect&, SkCanvas::QuadAAFlags, SkColor, SkBlendMode) override {} diff --git a/include/utils/SkPaintFilterCanvas.h b/include/utils/SkPaintFilterCanvas.h index c1d31b6e6d..0d154e5f04 100644 --- a/include/utils/SkPaintFilterCanvas.h +++ b/include/utils/SkPaintFilterCanvas.h @@ -68,6 +68,7 @@ protected: virtual bool onFilter(SkTCopyOnFirstWrite* paint, Type type) const = 0; void onDrawPaint(const SkPaint&) override; + void onDrawBehind(const SkPaint&) override; void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override; void onDrawRect(const SkRect&, const SkPaint&) override; void onDrawEdgeAARect(const SkRect&, SkCanvas::QuadAAFlags, SkColor, SkBlendMode) override; diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 13688504dc..f46575bf28 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1702,6 +1702,11 @@ void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 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()) { @@ -2127,6 +2132,41 @@ void SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) { 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()) { diff --git a/src/core/SkCanvasPriv.h b/src/core/SkCanvasPriv.h index cb2540177a..0c3a2d83ed 100644 --- a/src/core/SkCanvasPriv.h +++ b/src/core/SkCanvasPriv.h @@ -43,6 +43,16 @@ public: static int SaveBehind(SkCanvas* canvas, const SkRect* subset) { return canvas->only_axis_aligned_saveBehind(subset); } + + static void DrawBehind(SkCanvas* canvas, const SkPaint& paint) { + canvas->drawClippedToSaveBehind(paint); + } + + // The experimental_DrawEdgeAAImageSet API accepts separate dstClips and preViewMatrices arrays, + // where entries refer into them, but no explicit size is provided. Given a set of entries, + // computes the minimum length for these arrays that would provide index access errors. + static void GetDstClipAndMatrixCounts(const SkCanvas::ImageSetEntry set[], int count, + int* totalDstClipCount, int* totalMatrixCount); }; #endif diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp index 1c9c742894..562cd4f148 100644 --- a/src/core/SkLiteDL.cpp +++ b/src/core/SkLiteDL.cpp @@ -52,7 +52,7 @@ namespace { M(Flush) M(Save) M(Restore) M(SaveLayer) M(SaveBehind) \ M(Concat) M(SetMatrix) M(Translate) \ M(ClipPath) M(ClipRect) M(ClipRRect) M(ClipRegion) \ - M(DrawPaint) M(DrawPath) M(DrawRect) M(DrawEdgeAARect) \ + M(DrawPaint) M(DrawBehind) M(DrawPath) M(DrawRect) M(DrawEdgeAARect) \ M(DrawRegion) M(DrawOval) M(DrawArc) \ M(DrawRRect) M(DrawDRRect) M(DrawAnnotation) M(DrawDrawable) M(DrawPicture) \ M(DrawImage) M(DrawImageNine) M(DrawImageRect) M(DrawImageLattice) M(DrawImageSet) \ @@ -176,6 +176,12 @@ namespace { SkPaint paint; void draw(SkCanvas* c, const SkMatrix&) const { c->drawPaint(paint); } }; + struct DrawBehind final : Op { + static const auto kType = Type::DrawBehind; + DrawBehind(const SkPaint& paint) : paint(paint) {} + SkPaint paint; + void draw(SkCanvas* c, const SkMatrix&) const { SkCanvasPriv::DrawBehind(c, paint); } + }; struct DrawPath final : Op { static const auto kType = Type::DrawPath; DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {} @@ -527,6 +533,9 @@ void SkLiteDL::clipRegion(const SkRegion& region, SkClipOp op) { void SkLiteDL::drawPaint(const SkPaint& paint) { this->push(0, paint); } +void SkLiteDL::drawBehind(const SkPaint& paint) { + this->push(0, paint); +} void SkLiteDL::drawPath(const SkPath& path, const SkPaint& paint) { this->push(0, path, paint); } diff --git a/src/core/SkLiteDL.h b/src/core/SkLiteDL.h index a6041bc2d6..0758f01cd3 100644 --- a/src/core/SkLiteDL.h +++ b/src/core/SkLiteDL.h @@ -44,6 +44,7 @@ public: void clipRegion(const SkRegion&, SkClipOp); void drawPaint (const SkPaint&); + void drawBehind(const SkPaint&); void drawPath (const SkPath&, const SkPaint&); void drawRect (const SkRect&, const SkPaint&); void drawEdgeAARect(const SkRect&, SkCanvas::QuadAAFlags, SkColor, SkBlendMode); diff --git a/src/core/SkLiteRecorder.cpp b/src/core/SkLiteRecorder.cpp index 6dda8d6fa9..e4ea47e536 100644 --- a/src/core/SkLiteRecorder.cpp +++ b/src/core/SkLiteRecorder.cpp @@ -60,6 +60,9 @@ void SkLiteRecorder::onClipRegion(const SkRegion& region, SkClipOp op) { void SkLiteRecorder::onDrawPaint(const SkPaint& paint) { fDL->drawPaint(paint); } +void SkLiteRecorder::onDrawBehind(const SkPaint& paint) { + fDL->drawBehind(paint); +} void SkLiteRecorder::onDrawPath(const SkPath& path, const SkPaint& paint) { fDL->drawPath(path, paint); } diff --git a/src/core/SkLiteRecorder.h b/src/core/SkLiteRecorder.h index 81eedb341c..0bc5db3cf0 100644 --- a/src/core/SkLiteRecorder.h +++ b/src/core/SkLiteRecorder.h @@ -37,6 +37,7 @@ public: void onClipRegion(const SkRegion&, SkClipOp) override; void onDrawPaint (const SkPaint&) override; + void onDrawBehind(const SkPaint&) override; void onDrawPath (const SkPath&, const SkPaint&) override; void onDrawRect (const SkRect&, const SkPaint&) override; void onDrawEdgeAARect(const SkRect&, SkCanvas::QuadAAFlags, SkColor, SkBlendMode) override; diff --git a/src/core/SkOverdrawCanvas.cpp b/src/core/SkOverdrawCanvas.cpp index a7b39bbb66..a760ea0361 100644 --- a/src/core/SkOverdrawCanvas.cpp +++ b/src/core/SkOverdrawCanvas.cpp @@ -113,6 +113,10 @@ void SkOverdrawCanvas::onDrawPaint(const SkPaint& paint) { } } +void SkOverdrawCanvas::onDrawBehind(const SkPaint& paint) { + fList[0]->onDrawBehind(this->overdrawPaint(paint)); +} + void SkOverdrawCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) { fList[0]->onDrawRect(rect, this->overdrawPaint(paint)); } diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h index de1c269485..cdea96d77b 100644 --- a/src/core/SkPictureFlat.h +++ b/src/core/SkPictureFlat.h @@ -103,7 +103,9 @@ enum DrawType { DRAW_EDGEAA_RECT, - LAST_DRAWTYPE_ENUM = DRAW_EDGEAA_RECT, + DRAW_BEHIND_PAINT, + + LAST_DRAWTYPE_ENUM = DRAW_BEHIND_PAINT, }; enum DrawVertexFlags { diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index e0120dddfd..9724695fad 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -368,6 +368,14 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader, canvas->drawPaint(*paint); } } break; + case DRAW_BEHIND_PAINT: { + const SkPaint* paint = fPictureData->getPaint(reader); + BREAK_ON_READ_ERROR(reader); + + if (paint) { + SkCanvasPriv::DrawBehind(canvas, *paint); + } + } break; case DRAW_PATCH: { const SkPaint* paint = fPictureData->getPaint(reader); diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp index 01115bfdce..f7d5971535 100644 --- a/src/core/SkPictureRecord.cpp +++ b/src/core/SkPictureRecord.cpp @@ -422,6 +422,15 @@ void SkPictureRecord::onDrawPaint(const SkPaint& paint) { this->validate(initialOffset, size); } +void SkPictureRecord::onDrawBehind(const SkPaint& paint) { + // logically the same as drawPaint, but with a diff enum + // op + paint index + size_t size = 2 * kUInt32Size; + size_t initialOffset = this->addDraw(DRAW_BEHIND_PAINT, &size); + this->addPaint(paint); + this->validate(initialOffset, size); +} + void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { // op + paint index + mode + count + point data diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h index 77137c4716..59f16cf600 100644 --- a/src/core/SkPictureRecord.h +++ b/src/core/SkPictureRecord.h @@ -174,6 +174,7 @@ protected: SkBlendMode, const SkRect*, const SkPaint*) override; void onDrawPaint(const SkPaint&) override; + void onDrawBehind(const SkPaint&) override; void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override; void onDrawRect(const SkRect&, const SkPaint&) override; void onDrawEdgeAARect(const SkRect&, SkCanvas::QuadAAFlags, SkColor, SkBlendMode) override; diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index 4dcc45502f..fac7e68b14 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -88,6 +88,10 @@ template <> void Draw::draw(const SaveBehind& r) { SkCanvasPriv::SaveBehind(fCanvas, r.subset); } +template <> void Draw::draw(const DrawBehind& r) { + SkCanvasPriv::DrawBehind(fCanvas, r.paint); +} + DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix))); DRAW(Concat, concat(r.matrix)); DRAW(Translate, translate(r.dx, r.dy)); @@ -354,6 +358,7 @@ private: Bounds bounds(const Flush&) const { return fCullRect; } Bounds bounds(const DrawPaint&) const { return fCullRect; } + Bounds bounds(const DrawBehind&) const { return fCullRect; } Bounds bounds(const NoOp&) const { return Bounds::MakeEmpty(); } // NoOps don't draw. Bounds bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect, &op.paint); } diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp index bfe1067bbd..9a4e1f6a57 100644 --- a/src/core/SkRecorder.cpp +++ b/src/core/SkRecorder.cpp @@ -139,6 +139,10 @@ void SkRecorder::onDrawPaint(const SkPaint& paint) { this->append(paint); } +void SkRecorder::onDrawBehind(const SkPaint& paint) { + this->append(paint); +} + void SkRecorder::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h index 6b4c7fe1cd..53fd3aad73 100644 --- a/src/core/SkRecorder.h +++ b/src/core/SkRecorder.h @@ -77,6 +77,7 @@ public: const SkPaint& paint) override; void onDrawPaint(const SkPaint&) override; + void onDrawBehind(const SkPaint&) override; void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override; void onDrawRect(const SkRect&, const SkPaint&) override; void onDrawEdgeAARect(const SkRect&, SkCanvas::QuadAAFlags, SkColor, SkBlendMode) override; diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h index 8f80924ab4..66a5e283a1 100644 --- a/src/core/SkRecords.h +++ b/src/core/SkRecords.h @@ -60,6 +60,7 @@ namespace SkRecords { M(DrawImageSet) \ M(DrawDRRect) \ M(DrawOval) \ + M(DrawBehind) \ M(DrawPaint) \ M(DrawPath) \ M(DrawPatch) \ @@ -269,6 +270,8 @@ RECORD(DrawOval, kDraw_Tag|kHasPaint_Tag, SkRect oval); RECORD(DrawPaint, kDraw_Tag|kHasPaint_Tag, SkPaint paint); +RECORD(DrawBehind, kDraw_Tag|kHasPaint_Tag, + SkPaint paint); RECORD(DrawPath, kDraw_Tag|kHasPaint_Tag, SkPaint paint; PreCachedPath path); diff --git a/src/utils/SkNWayCanvas.cpp b/src/utils/SkNWayCanvas.cpp index 1e6cd89083..c952601154 100644 --- a/src/utils/SkNWayCanvas.cpp +++ b/src/utils/SkNWayCanvas.cpp @@ -147,6 +147,13 @@ void SkNWayCanvas::onDrawPaint(const SkPaint& paint) { } } +void SkNWayCanvas::onDrawBehind(const SkPaint& paint) { + Iter iter(fList); + while (iter.next()) { + SkCanvasPriv::DrawBehind(iter.get(), paint); + } +} + void SkNWayCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { Iter iter(fList); diff --git a/src/utils/SkPaintFilterCanvas.cpp b/src/utils/SkPaintFilterCanvas.cpp index ded7fc2fba..f06e565564 100644 --- a/src/utils/SkPaintFilterCanvas.cpp +++ b/src/utils/SkPaintFilterCanvas.cpp @@ -49,6 +49,13 @@ void SkPaintFilterCanvas::onDrawPaint(const SkPaint& paint) { } } +void SkPaintFilterCanvas::onDrawBehind(const SkPaint& paint) { + AutoPaintFilter apf(this, kPaint_Type, paint); + if (apf.shouldDraw()) { + this->SkNWayCanvas::onDrawBehind(*apf.paint()); + } +} + void SkPaintFilterCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { AutoPaintFilter apf(this, kPoint_Type, paint); diff --git a/tools/debugger/SkDebugCanvas.cpp b/tools/debugger/SkDebugCanvas.cpp index 96c0de2776..59d3dd8116 100644 --- a/tools/debugger/SkDebugCanvas.cpp +++ b/tools/debugger/SkDebugCanvas.cpp @@ -429,6 +429,10 @@ void SkDebugCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4 this->addDrawCommand(new SkDrawPatchCommand(cubics, colors, texCoords, bmode, paint)); } +void SkDebugCanvas::onDrawBehind(const SkPaint& paint) { + this->addDrawCommand(new SkDrawBehindCommand(paint)); +} + void SkDebugCanvas::onDrawVerticesObject(const SkVertices* vertices, const SkVertices::Bone bones[], int boneCount, SkBlendMode bmode, const SkPaint& paint) { // TODO: ANIMATION NOT LOGGED diff --git a/tools/debugger/SkDebugCanvas.h b/tools/debugger/SkDebugCanvas.h index 194ce119a9..83819bf6db 100644 --- a/tools/debugger/SkDebugCanvas.h +++ b/tools/debugger/SkDebugCanvas.h @@ -129,6 +129,7 @@ protected: void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], SkBlendMode, const SkPaint& paint) override; void onDrawPaint(const SkPaint&) override; + void onDrawBehind(const SkPaint&) override; void onDrawRect(const SkRect&, const SkPaint&) override; void onDrawEdgeAARect(const SkRect&, SkCanvas::QuadAAFlags, SkColor, SkBlendMode) override; diff --git a/tools/debugger/SkDrawCommand.cpp b/tools/debugger/SkDrawCommand.cpp index d9723acd7b..2de0c0cbf7 100644 --- a/tools/debugger/SkDrawCommand.cpp +++ b/tools/debugger/SkDrawCommand.cpp @@ -9,6 +9,7 @@ #include #include "SkAutoMalloc.h" +#include "SkCanvasPriv.h" #include "SkClipOpPriv.h" #include "SkColorFilter.h" #include "SkDashPathEffect.h" @@ -1639,6 +1640,27 @@ void SkDrawPathCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataMana writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT); MakeJsonPaint(writer, fPaint, urlDataManager); } +SkDrawBehindCommand::SkDrawBehindCommand(const SkPaint& paint) : INHERITED(kDrawPaint_OpType) { + fPaint = paint; +} + +void SkDrawBehindCommand::execute(SkCanvas* canvas) const { + SkCanvasPriv::DrawBehind(canvas, fPaint); +} + +bool SkDrawBehindCommand::render(SkCanvas* canvas) const { + canvas->clear(0xFFFFFFFF); + SkCanvasPriv::DrawBehind(canvas, fPaint); + return true; +} + +void SkDrawBehindCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const { + INHERITED::toJSON(writer, urlDataManager); + writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_PAINT); + MakeJsonPaint(writer, fPaint, urlDataManager); +} + + SkDrawRegionCommand::SkDrawRegionCommand(const SkRegion& region, const SkPaint& paint) : INHERITED(kDrawRegion_OpType) { fRegion = region; diff --git a/tools/debugger/SkDrawCommand.h b/tools/debugger/SkDrawCommand.h index 7c386bcbc8..50d2cc5403 100644 --- a/tools/debugger/SkDrawCommand.h +++ b/tools/debugger/SkDrawCommand.h @@ -419,6 +419,19 @@ private: typedef SkDrawCommand INHERITED; }; +class SkDrawBehindCommand : public SkDrawCommand { +public: + SkDrawBehindCommand(const SkPaint& paint); + void execute(SkCanvas* canvas) const override; + bool render(SkCanvas* canvas) const override; + void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override; + +private: + SkPaint fPaint; + + typedef SkDrawCommand INHERITED; +}; + class SkDrawPathCommand : public SkDrawCommand { public: SkDrawPathCommand(const SkPath& path, const SkPaint& paint); -- cgit v1.2.3 From 90019be56fc3dd1902d3bfa176fee9c27fe4380e Mon Sep 17 00:00:00 2001 From: Mike Reed Date: Tue, 23 Apr 2019 10:28:13 -0400 Subject: Fixes for saveBehind/drawBehind - fixes bug in device restore (was passing the wrong matrix) - use drawbehind for the clear, to avoid rounding differences between canvas and gpu Change-Id: I9c130e38437d8d34242620750f11a6ae7e62ff97 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/209801 Commit-Queue: Mike Reed Reviewed-by: Derek Sollenberger (cherry picked from commit 9adc82c73df0ef25b708cae8aa48ef9c39ed4c67) Reviewed-on: https://skia-review.googlesource.com/c/skia/+/211642 Auto-Submit: Derek Sollenberger Reviewed-by: Mike Reed Commit-Queue: Derek Sollenberger --- src/core/SkCanvas.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index f46575bf28..8e84c3205e 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1145,11 +1145,7 @@ void SkCanvas::internalSaveBehind(const SkRect* localBounds) { SkPaint paint; paint.setBlendMode(SkBlendMode::kClear); - if (localBounds) { - this->drawRect(*localBounds, paint); - } else { - this->drawPaint(paint); - } + this->drawClippedToSaveBehind(paint); } void SkCanvas::internalRestore() { @@ -2153,7 +2149,6 @@ void SkCanvas::onDrawBehind(const SkPaint& paint) { 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, @@ -2161,7 +2156,7 @@ void SkCanvas::onDrawBehind(const SkPaint& paint) { SkRegion rgn(bounds.makeOffset(dev->fOrigin.fX, dev->fOrigin.fY)); dev->clipRegion(rgn, SkClipOp::kIntersect); dev->drawPaint(looper.paint()); - dev->restore(ctm); + dev->restore(fMCRec->fMatrix); } LOOPER_END -- cgit v1.2.3