aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkMatrixClipStateMgr.cpp162
-rw-r--r--src/core/SkMatrixClipStateMgr.h51
-rw-r--r--src/core/SkPictureRecord.cpp1
-rw-r--r--tests/MatrixClipCollapseTest.cpp77
4 files changed, 164 insertions, 127 deletions
diff --git a/src/core/SkMatrixClipStateMgr.cpp b/src/core/SkMatrixClipStateMgr.cpp
index 4cf99bca97..872d60cc6b 100644
--- a/src/core/SkMatrixClipStateMgr.cpp
+++ b/src/core/SkMatrixClipStateMgr.cpp
@@ -21,7 +21,6 @@ bool SkMatrixClipStateMgr::MatrixClipState::ClipInfo::clipPath(SkPictureRecord*
newClip->fOp = op;
newClip->fDoAA = doAA;
newClip->fMatrixID = matrixID;
- newClip->fOffset = kInvalidJumpOffset;
return false;
}
@@ -36,7 +35,6 @@ bool SkMatrixClipStateMgr::MatrixClipState::ClipInfo::clipRegion(SkPictureRecord
newClip->fOp = op;
newClip->fDoAA = true; // not necessary but sanity preserving
newClip->fMatrixID = matrixID;
- newClip->fOffset = kInvalidJumpOffset;
return false;
}
@@ -55,17 +53,10 @@ void SkMatrixClipStateMgr::writeDeltaMat(int currentMatID, int desiredMatID) {
// Note: this only writes out the clips for the current save state. To get the
// entire clip stack requires iterating of the entire matrix/clip stack.
void SkMatrixClipStateMgr::MatrixClipState::ClipInfo::writeClip(int* curMatID,
- SkMatrixClipStateMgr* mgr,
- bool* overrideFirstOp) {
+ SkMatrixClipStateMgr* mgr) {
for (int i = 0; i < fClips.count(); ++i) {
ClipOp& curClip = fClips[i];
- SkRegion::Op op = curClip.fOp;
- if (*overrideFirstOp) {
- op = SkRegion::kReplace_Op;
- *overrideFirstOp = false;
- }
-
// TODO: use the matrix ID to skip writing the identity matrix
// over and over, i.e.:
// if (*curMatID != curClip.fMatrixID) {
@@ -79,43 +70,31 @@ void SkMatrixClipStateMgr::MatrixClipState::ClipInfo::writeClip(int* curMatID,
mgr->writeDeltaMat(*curMatID, curClip.fMatrixID);
*curMatID = curClip.fMatrixID;
+ int offset;
+
switch (curClip.fClipType) {
case kRect_ClipType:
- curClip.fOffset = mgr->getPicRecord()->recordClipRect(curClip.fGeom.fRRect.rect(),
- op, curClip.fDoAA);
+ offset = mgr->getPicRecord()->recordClipRect(curClip.fGeom.fRRect.rect(),
+ curClip.fOp, curClip.fDoAA);
break;
case kRRect_ClipType:
- curClip.fOffset = mgr->getPicRecord()->recordClipRRect(curClip.fGeom.fRRect, op,
- curClip.fDoAA);
+ offset = mgr->getPicRecord()->recordClipRRect(curClip.fGeom.fRRect, curClip.fOp,
+ curClip.fDoAA);
break;
case kPath_ClipType:
- curClip.fOffset = mgr->getPicRecord()->recordClipPath(curClip.fGeom.fPathID, op,
- curClip.fDoAA);
+ offset = mgr->getPicRecord()->recordClipPath(curClip.fGeom.fPathID, curClip.fOp,
+ curClip.fDoAA);
break;
case kRegion_ClipType: {
const SkRegion* region = mgr->lookupRegion(curClip.fGeom.fRegionID);
- curClip.fOffset = mgr->getPicRecord()->recordClipRegion(*region, op);
+ offset = mgr->getPicRecord()->recordClipRegion(*region, curClip.fOp);
break;
}
default:
SkASSERT(0);
}
- }
-}
-// Fill in the skip offsets for all the clips written in the current block
-void SkMatrixClipStateMgr::MatrixClipState::ClipInfo::fillInSkips(SkWriter32* writer,
- int32_t restoreOffset) {
- for (int i = 0; i < fClips.count(); ++i) {
- ClipOp& curClip = fClips[i];
-
- if (-1 == curClip.fOffset) {
- continue;
- }
-// SkDEBUGCODE(uint32_t peek = writer->read32At(curClip.fOffset);)
-// SkASSERT(-1 == peek);
- writer->overwriteTAt(curClip.fOffset, restoreOffset);
- SkDEBUGCODE(curClip.fOffset = -1;)
+ mgr->addClipOffset(offset);
}
}
@@ -126,6 +105,8 @@ SkMatrixClipStateMgr::SkMatrixClipStateMgr()
sizeof(fMatrixClipStackStorage))
, fCurOpenStateID(kIdentityWideOpenStateID) {
+ fSkipOffsets = SkNEW(SkTDArray<int>);
+
// The first slot in the matrix dictionary is reserved for the identity matrix
fMatrixDict.append()->reset();
@@ -137,12 +118,12 @@ SkMatrixClipStateMgr::~SkMatrixClipStateMgr() {
for (int i = 0; i < fRegionDict.count(); ++i) {
SkDELETE(fRegionDict[i]);
}
+
+ SkDELETE(fSkipOffsets);
}
-int SkMatrixClipStateMgr::save(SkCanvas::SaveFlags flags) {
- SkDEBUGCODE(this->validate();)
-
+int SkMatrixClipStateMgr::MCStackPush(SkCanvas::SaveFlags flags) {
MatrixClipState* newTop = (MatrixClipState*)fMatrixClipStack.push_back();
new (newTop) MatrixClipState(fCurMCState, flags); // balanced in restore()
fCurMCState = newTop;
@@ -152,14 +133,29 @@ int SkMatrixClipStateMgr::save(SkCanvas::SaveFlags flags) {
return fMatrixClipStack.count();
}
+int SkMatrixClipStateMgr::save(SkCanvas::SaveFlags flags) {
+ SkDEBUGCODE(this->validate();)
+
+ return this->MCStackPush(flags);
+}
+
int SkMatrixClipStateMgr::saveLayer(const SkRect* bounds, const SkPaint* paint,
SkCanvas::SaveFlags flags) {
- int result = this->save(flags);
+ // Since the saveLayer call draws something we need to potentially dump
+ // out the MC state
+ this->call(kOther_CallType);
+
+ int result = this->MCStackPush(flags);
++fCurMCState->fLayerID;
fCurMCState->fIsSaveLayer = true;
- fCurMCState->fSaveLayerBracketed = this->call(kOther_CallType);
fCurMCState->fSaveLayerBaseStateID = fCurOpenStateID;
+ fCurMCState->fSavedSkipOffsets = fSkipOffsets;
+
+ // TODO: recycle these rather then new & deleting them on every saveLayer/
+ // restore
+ fSkipOffsets = SkNEW(SkTDArray<int>);
+
fPicRecord->recordSaveLayer(bounds, paint,
(SkCanvas::SaveFlags)(flags| SkCanvas::kMatrixClip_SaveFlag));
return result;
@@ -170,21 +166,20 @@ void SkMatrixClipStateMgr::restore() {
if (fCurMCState->fIsSaveLayer) {
if (fCurMCState->fSaveLayerBaseStateID != fCurOpenStateID) {
- fPicRecord->recordRestore(); // Close the open block
+ fPicRecord->recordRestore(); // Close the open block inside the saveLayer
}
// The saveLayer's don't carry any matrix or clip state in the
// new scheme so make sure the saveLayer's recordRestore doesn't
// try to finalize them (i.e., fill in their skip offsets).
fPicRecord->recordRestore(false); // close of saveLayer
- // Close the Save that brackets the saveLayer. TODO: this doesn't handle
- // the skip offsets correctly
- if (fCurMCState->fSaveLayerBracketed) {
- fPicRecord->recordRestore(false);
- }
+ fCurOpenStateID = fCurMCState->fSaveLayerBaseStateID;
- // MC states can be allowed to fuse across saveLayer/restore boundaries
- fCurOpenStateID = kIdentityWideOpenStateID;
+ SkASSERT(0 == fSkipOffsets->count());
+ SkASSERT(NULL != fCurMCState->fSavedSkipOffsets);
+
+ SkDELETE(fSkipOffsets);
+ fSkipOffsets = fCurMCState->fSavedSkipOffsets;
}
fCurMCState->~MatrixClipState(); // balanced in save()
@@ -220,7 +215,11 @@ bool SkMatrixClipStateMgr::call(CallType callType) {
return false;
}
- if (kIdentityWideOpenStateID != fCurOpenStateID) {
+ if (kIdentityWideOpenStateID != fCurOpenStateID &&
+ (!fCurMCState->fIsSaveLayer ||
+ fCurMCState->fSaveLayerBaseStateID != fCurOpenStateID)) {
+ // 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.
fPicRecord->recordRestore(); // Close the open block
}
@@ -230,17 +229,40 @@ bool SkMatrixClipStateMgr::call(CallType callType) {
fPicRecord->recordSave(SkCanvas::kMatrixClip_SaveFlag);
// write out clips
- SkDeque::F2BIter iter(fMatrixClipStack);
- bool firstClip = true;
-
- int curMatID = kIdentityMatID;
- for (const MatrixClipState* state = (const MatrixClipState*) iter.next();
+ SkDeque::Iter iter(fMatrixClipStack, SkDeque::Iter::kBack_IterStart);
+ const MatrixClipState* state;
+ // Loop back across the MC states until the last saveLayer. The MC
+ // state in front of the saveLayer has already been written out.
+ for (state = (const MatrixClipState*) iter.prev();
state != NULL;
- state = (const MatrixClipState*) iter.next()) {
- state->fClipInfo->writeClip(&curMatID, this, &firstClip);
+ state = (const MatrixClipState*) iter.prev()) {
+ if (state->fIsSaveLayer) {
+ break;
+ }
+ }
+
+ if (NULL == state) {
+ // There was no saveLayer in the MC stack so we need to output them all
+ iter.reset(fMatrixClipStack, SkDeque::Iter::kFront_IterStart);
+ state = (const MatrixClipState*) iter.next();
+ } else {
+ // SkDeque's iterators actually return the previous location so we
+ // need to reverse and go forward one to get back on track.
+ iter.next();
+ SkDEBUGCODE(const MatrixClipState* test =) (const MatrixClipState*) iter.next();
+ SkASSERT(test == state);
+ }
+
+ int curMatID = NULL != state ? state->fMatrixInfo->getID(this) : kIdentityMatID;
+ for ( ; state != NULL; state = (const MatrixClipState*) iter.next()) {
+ state->fClipInfo->writeClip(&curMatID, this);
}
// write out matrix
+ // TODO: this test isn't quite right. It should be:
+ // if (curMatID != fCurMCState->fMatrixInfo->getID(this)) {
+ // but right now the testing harness always expects a matrix if
+ // the matrices are non-I
if (kIdentityMatID != fCurMCState->fMatrixInfo->getID(this)) {
// TODO: writing out the delta matrix here is an artifact of the writing
// out of the entire clip stack (with its matrices). Ultimately we will
@@ -253,6 +275,17 @@ bool SkMatrixClipStateMgr::call(CallType callType) {
return true;
}
+// Fill in the skip offsets for all the clips written in the current block
+void SkMatrixClipStateMgr::fillInSkips(SkWriter32* writer, int32_t restoreOffset) {
+ for (int i = 0; i < fSkipOffsets->count(); ++i) {
+ SkDEBUGCODE(uint32_t peek = writer->readTAt<int32_t>((*fSkipOffsets)[i]);)
+ SkASSERT(-1 == peek);
+ writer->overwriteTAt<int32_t>((*fSkipOffsets)[i], restoreOffset);
+ }
+
+ fSkipOffsets->rewind();
+}
+
void SkMatrixClipStateMgr::finish() {
if (kIdentityWideOpenStateID != fCurOpenStateID) {
fPicRecord->recordRestore(); // Close the open block
@@ -262,16 +295,23 @@ void SkMatrixClipStateMgr::finish() {
#ifdef SK_DEBUG
void SkMatrixClipStateMgr::validate() {
- if (fCurOpenStateID == fCurMCState->fMCStateID) {
- // The current state is the active one so all its skip offsets should
- // still be -1
- SkDeque::F2BIter iter(fMatrixClipStack);
-
- for (const MatrixClipState* state = (const MatrixClipState*) iter.next();
+ if (fCurOpenStateID == fCurMCState->fMCStateID &&
+ (!fCurMCState->fIsSaveLayer ||
+ fCurOpenStateID != fCurMCState->fSaveLayerBaseStateID)) {
+ // The current state is the active one so it should have a skip
+ // offset for each clip
+ SkDeque::Iter iter(fMatrixClipStack, SkDeque::Iter::kBack_IterStart);
+ int clipCount = 0;
+ for (const MatrixClipState* state = (const MatrixClipState*) iter.prev();
state != NULL;
- state = (const MatrixClipState*) iter.next()) {
- state->fClipInfo->checkOffsetNotEqual(-1);
+ state = (const MatrixClipState*) iter.prev()) {
+ clipCount += state->fClipInfo->numClips();
+ if (state->fIsSaveLayer) {
+ break;
+ }
}
+
+ SkASSERT(fSkipOffsets->count() == clipCount);
}
}
#endif
diff --git a/src/core/SkMatrixClipStateMgr.h b/src/core/SkMatrixClipStateMgr.h
index 60f9fa0016..ef0a99dbfa 100644
--- a/src/core/SkMatrixClipStateMgr.h
+++ b/src/core/SkMatrixClipStateMgr.h
@@ -120,7 +120,6 @@ public:
newClip->fOp = op;
newClip->fDoAA = doAA;
newClip->fMatrixID = matrixID;
- newClip->fOffset = kInvalidJumpOffset;
return false;
}
@@ -134,7 +133,6 @@ public:
newClip->fOp = op;
newClip->fDoAA = doAA;
newClip->fMatrixID = matrixID;
- newClip->fOffset = kInvalidJumpOffset;
return false;
}
@@ -147,19 +145,10 @@ public:
int regionID,
SkRegion::Op op,
int matrixID);
- void writeClip(int* curMatID,
- SkMatrixClipStateMgr* mgr,
- bool* overrideFirstOp);
- void fillInSkips(SkWriter32* writer, int32_t restoreOffset);
+ void writeClip(int* curMatID, SkMatrixClipStateMgr* mgr);
+
+ SkDEBUGCODE(int numClips() const { return fClips.count(); })
-#ifdef SK_DEBUG
- void checkOffsetNotEqual(int32_t offset) {
- for (int i = 0; i < fClips.count(); ++i) {
- ClipOp& curClip = fClips[i];
- SkASSERT(offset != curClip.fOffset);
- }
- }
-#endif
private:
enum ClipType {
kRect_ClipType,
@@ -168,8 +157,6 @@ public:
kRegion_ClipType
};
- static const int kInvalidJumpOffset = -1;
-
class ClipOp {
public:
ClipType fClipType;
@@ -185,10 +172,6 @@ public:
// The CTM in effect when this clip call was issued
int fMatrixID;
-
- // The offset of this clipOp's "jump-to-offset" location in the skp.
- // -1 means the offset hasn't been written.
- int32_t fOffset;
};
SkTDArray<ClipOp> fClips;
@@ -249,7 +232,7 @@ public:
// The next two fields are only valid when fIsSaveLayer is set.
int32_t fSaveLayerBaseStateID;
- bool fSaveLayerBracketed;
+ SkTDArray<int>* fSavedSkipOffsets;
#ifdef SK_DEBUG
MatrixClipState* fPrev; // debugging aid
@@ -347,17 +330,7 @@ public:
bool call(CallType callType);
- void fillInSkips(SkWriter32* writer, int32_t restoreOffset) {
- // Since we write out the entire clip stack at each block start we
- // need to update the skips for the entire stack each time too.
- SkDeque::F2BIter iter(fMatrixClipStack);
-
- for (const MatrixClipState* state = (const MatrixClipState*) iter.next();
- state != NULL;
- state = (const MatrixClipState*) iter.next()) {
- state->fClipInfo->fillInSkips(writer, restoreOffset);
- }
- }
+ void fillInSkips(SkWriter32* writer, int32_t restoreOffset);
void finish();
@@ -379,9 +352,23 @@ protected:
// The MCStateID of the state currently in effect in the byte stream. 0 if none.
int32_t fCurOpenStateID;
+ // The skip offsets for the current open state. These are the locations in the
+ // skp that must be filled in when the current open state is closed. These are
+ // here rather then distributed across the MatrixClipState's because saveLayers
+ // can cause MC states to be nested.
+ SkTDArray<int32_t> *fSkipOffsets;
SkDEBUGCODE(void validate();)
+ int MCStackPush(SkCanvas::SaveFlags flags);
+
+ void addClipOffset(int offset) {
+ SkASSERT(NULL != fSkipOffsets);
+ SkASSERT(kIdentityWideOpenStateID != fCurOpenStateID);
+
+ *fSkipOffsets->append() = offset;
+ }
+
void writeDeltaMat(int currentMatID, int desiredMatID);
static int32_t NewMCStateID();
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 5890ac4bf0..c14328b7a8 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -598,7 +598,6 @@ void SkPictureRecord::restore() {
return;
}
- // TODO: don't write the restore to the op stream for normal saves
fMCMgr.restore();
#else
// check for underflow
diff --git a/tests/MatrixClipCollapseTest.cpp b/tests/MatrixClipCollapseTest.cpp
index d379e3351c..6981fe25d4 100644
--- a/tests/MatrixClipCollapseTest.cpp
+++ b/tests/MatrixClipCollapseTest.cpp
@@ -129,10 +129,14 @@ enum DrawOpType {
kDrawVertices_DrawOpType,
#endif
- kLast_DrawOpType = kRect_DrawOpType
+ kLastNonSaveLayer_DrawOpType = kRect_DrawOpType,
+
+ // saveLayer's have to handled apart from the other draw operations
+ // since they also alter the save/restore structure.
+ kSaveLayer_DrawOpType,
};
-static const int kDrawOpTypeCount = kLast_DrawOpType + 1;
+static const int kNonSaveLayerDrawOpTypeCount = kLastNonSaveLayer_DrawOpType + 1;
typedef void (*PFEmitMC)(SkCanvas* canvas, MatType mat, ClipType clip,
DrawOpType draw, SkTDArray<DrawType>* expected,
@@ -321,13 +325,13 @@ static void emit_draw(SkCanvas* canvas, DrawOpType draw, SkTDArray<DrawType>* ex
static void emit_clip_and_mat(SkCanvas* canvas, MatType mat, ClipType clip,
DrawOpType draw, SkTDArray<DrawType>* expected,
int accumulatedClips) {
+ emit_clip(canvas, clip);
+ emit_mat(canvas, mat);
+
if (kNone_DrawOpType == draw) {
return;
}
- emit_clip(canvas, clip);
- emit_mat(canvas, mat);
-
for (int i = 0; i < accumulatedClips; ++i) {
add_clip(clip, mat, expected);
}
@@ -342,13 +346,13 @@ static void emit_clip_and_mat(SkCanvas* canvas, MatType mat, ClipType clip,
static void emit_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip,
DrawOpType draw, SkTDArray<DrawType>* expected,
int accumulatedClips) {
+ emit_mat(canvas, mat);
+ emit_clip(canvas, clip);
+
if (kNone_DrawOpType == draw) {
return;
}
- emit_mat(canvas, mat);
- emit_clip(canvas, clip);
-
// the matrix & clip order will be reversed once collapsed!
for (int i = 0; i < accumulatedClips; ++i) {
add_clip(clip, mat, expected);
@@ -365,15 +369,15 @@ static void emit_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip,
static void emit_double_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType clip,
DrawOpType draw, SkTDArray<DrawType>* expected,
int accumulatedClips) {
- if (kNone_DrawOpType == draw) {
- return;
- }
-
emit_mat(canvas, mat);
emit_clip(canvas, clip);
emit_mat(canvas, mat);
emit_clip(canvas, clip);
+ if (kNone_DrawOpType == draw) {
+ return;
+ }
+
for (int i = 0; i < accumulatedClips; ++i) {
add_clip(clip, mat, expected);
add_clip(clip, mat, expected);
@@ -390,14 +394,14 @@ static void emit_double_mat_and_clip(SkCanvas* canvas, MatType mat, ClipType cli
static void emit_mat_clip_clip(SkCanvas* canvas, MatType mat, ClipType clip,
DrawOpType draw, SkTDArray<DrawType>* expected,
int accumulatedClips) {
- if (kNone_DrawOpType == draw) {
- return;
- }
-
emit_mat(canvas, mat);
emit_clip(canvas, clip);
emit_clip(canvas, clip);
+ if (kNone_DrawOpType == draw) {
+ return;
+ }
+
for (int i = 0; i < accumulatedClips; ++i) {
add_clip(clip, mat, expected);
add_clip(clip, mat, expected);
@@ -465,22 +469,24 @@ static void emit_body2(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
bool needsSaveRestore = kNone_DrawOpType != draw &&
(kNone_MatType != mat || kNone_ClipType != clip);
- if (needsSaveRestore) {
- *expected->append() = SAVE_LAYER;
+ if (kNone_MatType != mat || kNone_ClipType != clip) {
+ *expected->append() = SAVE;
}
- (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops
+ (*emitMC)(canvas, mat, clip, kSaveLayer_DrawOpType, expected, accumulatedClips+1);
+ *expected->append() = SAVE_LAYER;
// TODO: widen testing to exercise saveLayer's parameters
canvas->saveLayer(NULL, NULL);
if (needsSaveRestore) {
*expected->append() = SAVE;
}
- (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+2);
+ (*emitMC)(canvas, mat, clip, draw, expected, 1);
emit_draw(canvas, draw, expected);
if (needsSaveRestore) {
*expected->append() = RESTORE;
}
canvas->restore();
- if (needsSaveRestore) {
+ *expected->append() = RESTORE;
+ if (kNone_MatType != mat || kNone_ClipType != clip) {
*expected->append() = RESTORE;
}
}
@@ -501,35 +507,39 @@ static void emit_body3(SkCanvas* canvas, PFEmitMC emitMC, MatType mat,
bool needsSaveRestore = kNone_DrawOpType != draw &&
(kNone_MatType != mat || kNone_ClipType != clip);
- // This saveLayer will always be forced b.c. we currently can't tell
- // ahead of time if it will be empty (see comment in SkMatrixClipStateMgr::save)
+ if (kNone_MatType != mat || kNone_ClipType != clip) {
+ *expected->append() = SAVE;
+ }
+ (*emitMC)(canvas, mat, clip, kSaveLayer_DrawOpType, expected, accumulatedClips+1);
*expected->append() = SAVE_LAYER;
-
- (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops
// TODO: widen testing to exercise saveLayer's parameters
canvas->saveLayer(NULL, NULL);
- (*emitMC)(canvas, mat, clip, draw, NULL, 0); // these get fused into later ops
- if (needsSaveRestore) {
- *expected->append() = SAVE_LAYER;
+ (*emitMC)(canvas, mat, clip, kSaveLayer_DrawOpType, expected, 1);
+ if (kNone_MatType != mat || kNone_ClipType != clip) {
+ *expected->append() = SAVE;
}
+ *expected->append() = SAVE_LAYER;
// TODO: widen testing to exercise saveLayer's parameters
canvas->saveLayer(NULL, NULL);
if (needsSaveRestore) {
*expected->append() = SAVE;
}
- (*emitMC)(canvas, mat, clip, draw, expected, accumulatedClips+3);
+ (*emitMC)(canvas, mat, clip, draw, expected, 1);
emit_draw(canvas, draw, expected);
if (needsSaveRestore) {
*expected->append() = RESTORE;
}
- canvas->restore();
- if (needsSaveRestore) {
+ canvas->restore(); // for saveLayer
+ *expected->append() = RESTORE; // for saveLayer
+ if (kNone_MatType != mat || kNone_ClipType != clip) {
*expected->append() = RESTORE;
}
canvas->restore();
-
// required to match forced SAVE_LAYER
*expected->append() = RESTORE;
+ if (kNone_MatType != mat || kNone_ClipType != clip) {
+ *expected->append() = RESTORE;
+ }
}
//////////////////////////////////////////////////////////////////////////////
@@ -660,13 +670,14 @@ static void test_collapse(skiatest::Reporter* reporter) {
for (size_t k = 0; k < SK_ARRAY_COUNT(gMCs); ++k) {
for (int l = 0; l < kMatTypeCount; ++l) {
for (int m = 0; m < kClipTypeCount; ++m) {
- for (int n = 0; n < kDrawOpTypeCount; ++n) {
+ for (int n = 0; n < kNonSaveLayerDrawOpTypeCount; ++n) {
#ifdef TEST_COLLAPSE_MATRIX_CLIP_STATE
static int testID = -1;
++testID;
if (testID < -1) {
continue;
}
+ SkDebugf("test: %d\n", testID);
#endif
SkTDArray<DrawType> expected, actual;