From c3b589a24eb4d567a906189f882c259ecf5c2f58 Mon Sep 17 00:00:00 2001 From: fmalita Date: Thu, 5 Jun 2014 12:40:07 -0700 Subject: [PATCH] SkClipStack::Element tweaks. ( This is intended to facilitate efficient kMatrix_SaveFlags emulation on restore(): * collect all clip stack elements for the current save count into a side clip stack * canvas.restore(everything) * replay the collected clip ops to restore the initial clip state => we restored the matrix but the clip state is unchanged ) Two main changes: * expose the save count for SkClipStack::Element * expose a replay method for the same (logic relocated from SkCanvas::replayClips) The SkCanvas::ClipVisitor shuffling is to enable forward decl in SkClipStack.h (cannot fwdecl a nested class). R=reed@google.com, robertphillips@google.com TBR=reed@google.com Author: fmalita@chromium.org Review URL: https://codereview.chromium.org/269693003 --- include/core/SkCanvas.h | 17 +++++++++-------- include/core/SkClipStack.h | 9 +++++++++ src/core/SkCanvas.cpp | 18 ++---------------- src/core/SkClipStack.cpp | 22 +++++++++++++++++++++- 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index ee8ad250d2..b92b1460fd 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -24,6 +24,7 @@ #define SK_LEGACY_DRAWTEXT_VIRTUAL #endif +class SkCanvasClipVisitor; class SkBaseDevice; class SkDraw; class SkDrawFilter; @@ -1134,14 +1135,7 @@ public: return &fClipStack; } - class ClipVisitor { - public: - virtual ~ClipVisitor(); - virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0; - virtual void clipRRect(const SkRRect&, SkRegion::Op, bool antialias) = 0; - virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0; - }; - + typedef SkCanvasClipVisitor ClipVisitor; /** * Replays the clip operations, back to front, that have been applied to * the canvas, calling the appropriate method on the visitor for each @@ -1504,5 +1498,12 @@ static inline SkCanvas::SaveFlags& operator|=(SkCanvas::SaveFlags& lhs, return lhs; } +class SkCanvasClipVisitor { +public: + virtual ~SkCanvasClipVisitor(); + virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0; + virtual void clipRRect(const SkRRect&, SkRegion::Op, bool antialias) = 0; + virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0; +}; #endif diff --git a/include/core/SkClipStack.h b/include/core/SkClipStack.h index 028d551560..4243cee7b0 100644 --- a/include/core/SkClipStack.h +++ b/include/core/SkClipStack.h @@ -16,6 +16,7 @@ #include "SkTDArray.h" #include "SkTLazy.h" +class SkCanvasClipVisitor; // Because a single save/restore state can have multiple clips, this class // stores the stack depth (fSaveCount) and clips (fDeque) separately. @@ -74,6 +75,9 @@ public: //!< Call to get the type of the clip element. Type getType() const { return fType; } + //!< Call to get the save count associated with this clip element. + int getSaveCount() const { return fSaveCount; } + //!< Call if getType() is kPath to get the path. const SkPath& getPath() const { SkASSERT(kPath_Type == fType); return *fPath.get(); } @@ -156,6 +160,11 @@ public: return kPath_Type == fType && fPath.get()->isInverseFillType(); } + /** + * Replay this clip into the visitor. + */ + void replay(SkCanvasClipVisitor*) const; + private: friend class SkClipStack; diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 3134c46686..bdbcd3be74 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1666,22 +1666,8 @@ void SkCanvas::replayClips(ClipVisitor* visitor) const { SkClipStack::B2TIter iter(fClipStack); const SkClipStack::Element* element; - static const SkRect kEmpty = { 0, 0, 0, 0 }; while ((element = iter.next()) != NULL) { - switch (element->getType()) { - case SkClipStack::Element::kPath_Type: - visitor->clipPath(element->getPath(), element->getOp(), element->isAA()); - break; - case SkClipStack::Element::kRRect_Type: - visitor->clipRRect(element->getRRect(), element->getOp(), element->isAA()); - break; - case SkClipStack::Element::kRect_Type: - visitor->clipRect(element->getRect(), element->getOp(), element->isAA()); - break; - case SkClipStack::Element::kEmpty_Type: - visitor->clipRect(kEmpty, SkRegion::kIntersect_Op, false); - break; - } + element->replay(visitor); } } @@ -2556,7 +2542,7 @@ int SkCanvas::LayerIter::y() const { return fImpl->getY(); } /////////////////////////////////////////////////////////////////////////////// -SkCanvas::ClipVisitor::~ClipVisitor() { } +SkCanvasClipVisitor::~SkCanvasClipVisitor() { } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkClipStack.cpp b/src/core/SkClipStack.cpp index b60a6c961d..d087592b17 100644 --- a/src/core/SkClipStack.cpp +++ b/src/core/SkClipStack.cpp @@ -1,10 +1,11 @@ - /* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ + +#include "SkCanvas.h" #include "SkClipStack.h" #include "SkPath.h" #include "SkThread.h" @@ -66,6 +67,25 @@ bool SkClipStack::Element::operator== (const Element& element) const { } } +void SkClipStack::Element::replay(SkCanvasClipVisitor* visitor) const { + static const SkRect kEmptyRect = { 0, 0, 0, 0 }; + + switch (fType) { + case kPath_Type: + visitor->clipPath(this->getPath(), this->getOp(), this->isAA()); + break; + case kRRect_Type: + visitor->clipRRect(this->getRRect(), this->getOp(), this->isAA()); + break; + case kRect_Type: + visitor->clipRect(this->getRect(), this->getOp(), this->isAA()); + break; + case kEmpty_Type: + visitor->clipRect(kEmptyRect, SkRegion::kIntersect_Op, false); + break; + } +} + void SkClipStack::Element::invertShapeFillType() { switch (fType) { case kRect_Type: