I believe this makes it clearer what is going on; namely:

saveLayers cause their enclosing MC state to become a prefix for their child canvas calls. In such cases we don't want to inadvertently close the nesting MC state but when we do (i.e., when the saveLayer's restore is seen) we want to also restore the nesting MC state to be the current one.

R=bsalomon@google.com

Author: robertphillips@google.com

Review URL: https://codereview.chromium.org/176413002

git-svn-id: http://skia.googlecode.com/svn/trunk@13564 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2014-02-24 17:24:15 +00:00
parent 2e34b21dc5
commit 6c5f1fd66c
2 changed files with 18 additions and 29 deletions

View File

@ -28,7 +28,6 @@ bool SkMatrixClipStateMgr::MatrixClipState::ClipInfo::clipRegion(SkPictureRecord
int regionID, int regionID,
SkRegion::Op op, SkRegion::Op op,
int matrixID) { int matrixID) {
// TODO: add a region dictionary so we don't have to copy the region in here
ClipOp* newClip = fClips.append(); ClipOp* newClip = fClips.append();
newClip->fClipType = kRegion_ClipType; newClip->fClipType = kRegion_ClipType;
newClip->fGeom.fRegionID = regionID; newClip->fGeom.fRegionID = regionID;
@ -166,7 +165,7 @@ int SkMatrixClipStateMgr::saveLayer(const SkRect* bounds, const SkPaint* paint,
fCurMCState->fExpectedDepth++; // 1 for saveLayer fCurMCState->fExpectedDepth++; // 1 for saveLayer
#endif #endif
fCurMCState->fSaveLayerBaseStateID = fCurOpenStateID; *fStateIDStack.append() = fCurOpenStateID;
fCurMCState->fSavedSkipOffsets = fSkipOffsets; fCurMCState->fSavedSkipOffsets = fSkipOffsets;
// TODO: recycle these rather then new & deleting them on every saveLayer/ // TODO: recycle these rather then new & deleting them on every saveLayer/
@ -205,7 +204,9 @@ void SkMatrixClipStateMgr::restore() {
fActualDepth--; fActualDepth--;
#endif #endif
fCurOpenStateID = fCurMCState->fSaveLayerBaseStateID; SkASSERT(fStateIDStack.count() >= 1);
fCurOpenStateID = fStateIDStack[fStateIDStack.count()-1];
fStateIDStack.pop();
SkASSERT(0 == fSkipOffsets->count()); SkASSERT(0 == fSkipOffsets->count());
SkASSERT(NULL != fCurMCState->fSavedSkipOffsets); SkASSERT(NULL != fCurMCState->fSavedSkipOffsets);
@ -243,23 +244,8 @@ int32_t SkMatrixClipStateMgr::NewMCStateID() {
return gMCStateID; return gMCStateID;
} }
bool SkMatrixClipStateMgr::isCurrentlyOpen(int32_t stateID) { bool SkMatrixClipStateMgr::isNestingMCState(int stateID) {
if (fCurMCState->fIsSaveLayer) return fStateIDStack.count() > 0 && fStateIDStack[fStateIDStack.count()-1] == fCurOpenStateID;
return false;
SkDeque::Iter iter(fMatrixClipStack, SkDeque::Iter::kBack_IterStart);
for (const MatrixClipState* state = (const MatrixClipState*) iter.prev();
state != NULL;
state = (const MatrixClipState*) iter.prev()) {
if (state->fIsSaveLayer) {
if (state->fSaveLayerBaseStateID == stateID) {
return true;
}
}
}
return false;
} }
bool SkMatrixClipStateMgr::call(CallType callType) { bool SkMatrixClipStateMgr::call(CallType callType) {
@ -280,7 +266,7 @@ bool SkMatrixClipStateMgr::call(CallType callType) {
} }
if (kIdentityWideOpenStateID != fCurOpenStateID && if (kIdentityWideOpenStateID != fCurOpenStateID &&
!this->isCurrentlyOpen(fCurOpenStateID)) { !this->isNestingMCState(fCurOpenStateID)) {
// Don't write a restore if the open state is one in which a saveLayer // Don't write a restore if the open state is one in which a saveLayer
// is nested. The save after the saveLayer's restore will close it. // is nested. The save after the saveLayer's restore will close it.
fPicRecord->recordRestore(); // Close the open block fPicRecord->recordRestore(); // Close the open block
@ -397,9 +383,7 @@ void SkMatrixClipStateMgr::finish() {
#ifdef SK_DEBUG #ifdef SK_DEBUG
void SkMatrixClipStateMgr::validate() { void SkMatrixClipStateMgr::validate() {
if (fCurOpenStateID == fCurMCState->fMCStateID && if (fCurOpenStateID == fCurMCState->fMCStateID && !this->isNestingMCState(fCurOpenStateID)) {
(!fCurMCState->fIsSaveLayer ||
fCurOpenStateID != fCurMCState->fSaveLayerBaseStateID)) {
// The current state is the active one so it should have a skip // The current state is the active one so it should have a skip
// offset for each clip // offset for each clip
SkDeque::Iter iter(fMatrixClipStack, SkDeque::Iter::kBack_IterStart); SkDeque::Iter iter(fMatrixClipStack, SkDeque::Iter::kBack_IterStart);

View File

@ -53,7 +53,7 @@ public:
static const int32_t kIdentityWideOpenStateID = 0; static const int32_t kIdentityWideOpenStateID = 0;
static const int kIdentityMatID = 0; static const int kIdentityMatID = 0;
class MatrixClipState { class MatrixClipState : public SkNoncopyable {
public: public:
class MatrixInfo { class MatrixInfo {
public: public:
@ -104,6 +104,8 @@ public:
private: private:
SkMatrix fMatrix; SkMatrix fMatrix;
int fMatrixID; int fMatrixID;
typedef SkNoncopyable INHERITED;
}; };
class ClipInfo : public SkNoncopyable { class ClipInfo : public SkNoncopyable {
@ -162,7 +164,7 @@ public:
ClipType fClipType; ClipType fClipType;
union { union {
SkRRect fRRect; // also stores clipRect SkRRect fRRect; // also stores clip rect
int fPathID; int fPathID;
int fRegionID; int fRegionID;
} fGeom; } fGeom;
@ -236,8 +238,7 @@ public:
// Does this MC state represent a saveLayer call? // Does this MC state represent a saveLayer call?
bool fIsSaveLayer; bool fIsSaveLayer;
// The next two fields are only valid when fIsSaveLayer is set. // The next field is only valid when fIsSaveLayer is set.
int32_t fSaveLayerBaseStateID;
SkTDArray<int>* fSavedSkipOffsets; SkTDArray<int>* fSavedSkipOffsets;
// Does the MC state have an open block in the skp? // Does the MC state have an open block in the skp?
@ -399,11 +400,15 @@ protected:
return fMatrixDict[index]; return fMatrixDict[index];
} }
bool isCurrentlyOpen(int32_t stateID); bool isNestingMCState(int stateID);
#ifdef SK_DEBUG #ifdef SK_DEBUG
int fActualDepth; int fActualDepth;
#endif #endif
// save layers are nested within a specific MC state. This stack tracks
// the nesting MC state's ID as save layers are pushed and popped.
SkTDArray<int> fStateIDStack;
}; };
#endif #endif