Index: src/core/SkMatrixClipStateMgr.cpp |
diff --git a/src/core/SkMatrixClipStateMgr.cpp b/src/core/SkMatrixClipStateMgr.cpp |
deleted file mode 100644 |
index 680cc364d25b5cf01b3601fc4f5895023e5bf304..0000000000000000000000000000000000000000 |
--- a/src/core/SkMatrixClipStateMgr.cpp |
+++ /dev/null |
@@ -1,419 +0,0 @@ |
-/* |
- * Copyright 2014 Google Inc. |
- * |
- * Use of this source code is governed by a BSD-style license that can be |
- * found in the LICENSE file. |
- */ |
- |
-#include "SkMatrixClipStateMgr.h" |
-#include "SkPictureRecord.h" |
- |
-bool SkMatrixClipStateMgr::MatrixClipState::ClipInfo::clipPath(SkPictureRecord* picRecord, |
- const SkPath& path, |
- SkRegion::Op op, |
- bool doAA, |
- int matrixID) { |
- int pathID = picRecord->addPathToHeap(path); |
- |
- ClipOp* newClip = fClips.append(); |
- newClip->fClipType = kPath_ClipType; |
- newClip->fGeom.fPathID = pathID; |
- newClip->fOp = op; |
- newClip->fDoAA = doAA; |
- newClip->fMatrixID = matrixID; |
- return false; |
-} |
- |
-bool SkMatrixClipStateMgr::MatrixClipState::ClipInfo::clipRegion(SkPictureRecord* picRecord, |
- int regionID, |
- SkRegion::Op op, |
- int matrixID) { |
- ClipOp* newClip = fClips.append(); |
- newClip->fClipType = kRegion_ClipType; |
- newClip->fGeom.fRegionID = regionID; |
- newClip->fOp = op; |
- newClip->fDoAA = true; // not necessary but sanity preserving |
- newClip->fMatrixID = matrixID; |
- return false; |
-} |
- |
-void SkMatrixClipStateMgr::writeDeltaMat(int currentMatID, int desiredMatID) { |
- const SkMatrix& current = this->lookupMat(currentMatID); |
- const SkMatrix& desired = this->lookupMat(desiredMatID); |
- |
- SkMatrix delta; |
- bool result = current.invert(&delta); |
- if (result) { |
- delta.preConcat(desired); |
- } |
- fPicRecord->recordConcat(delta); |
-} |
- |
-// 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) { |
- for (int i = 0; i < fClips.count(); ++i) { |
- ClipOp& curClip = fClips[i]; |
- |
- // TODO: use the matrix ID to skip writing the identity matrix |
- // over and over, i.e.: |
- // if (*curMatID != curClip.fMatrixID) { |
- // mgr->writeDeltaMat... |
- // *curMatID... |
- // } |
- // Right now this optimization would throw off the testing harness. |
- // TODO: right now we're writing out the delta matrix from the prior |
- // matrix state. This is a side-effect of writing out the entire |
- // clip stack and should be resolved when that is fixed. |
- mgr->writeDeltaMat(*curMatID, curClip.fMatrixID); |
- *curMatID = curClip.fMatrixID; |
- |
- size_t offset = 0; |
- |
- switch (curClip.fClipType) { |
- case kRect_ClipType: |
- offset = mgr->getPicRecord()->recordClipRect(curClip.fGeom.fRRect.rect(), |
- curClip.fOp, curClip.fDoAA); |
- break; |
- case kRRect_ClipType: |
- offset = mgr->getPicRecord()->recordClipRRect(curClip.fGeom.fRRect, curClip.fOp, |
- curClip.fDoAA); |
- break; |
- case kPath_ClipType: |
- offset = mgr->getPicRecord()->recordClipPath(curClip.fGeom.fPathID, curClip.fOp, |
- curClip.fDoAA); |
- break; |
- case kRegion_ClipType: { |
- const SkRegion* region = mgr->lookupRegion(curClip.fGeom.fRegionID); |
- offset = mgr->getPicRecord()->recordClipRegion(*region, curClip.fOp); |
- break; |
- } |
- default: |
- SkASSERT(0); |
- } |
- |
- mgr->addClipOffset(offset); |
- } |
-} |
- |
-SkMatrixClipStateMgr::SkMatrixClipStateMgr() |
- : fPicRecord(NULL) |
- , fMatrixClipStack(sizeof(MatrixClipState), |
- fMatrixClipStackStorage, |
- sizeof(fMatrixClipStackStorage)) |
- , fCurOpenStateID(kIdentityWideOpenStateID) { |
- |
- fSkipOffsets = SkNEW(SkTDArray<int>); |
- |
- // The first slot in the matrix dictionary is reserved for the identity matrix |
- fMatrixDict.append()->reset(); |
- |
- fCurMCState = (MatrixClipState*)fMatrixClipStack.push_back(); |
- new (fCurMCState) MatrixClipState(NULL); // balanced in restore() |
- |
-#ifdef SK_DEBUG |
- fActualDepth = 0; |
-#endif |
-} |
- |
-SkMatrixClipStateMgr::~SkMatrixClipStateMgr() { |
- for (int i = 0; i < fRegionDict.count(); ++i) { |
- SkDELETE(fRegionDict[i]); |
- } |
- |
- SkDELETE(fSkipOffsets); |
-} |
- |
- |
-int SkMatrixClipStateMgr::MCStackPush() { |
- MatrixClipState* newTop = (MatrixClipState*)fMatrixClipStack.push_back(); |
- new (newTop) MatrixClipState(fCurMCState); // balanced in restore() |
- fCurMCState = newTop; |
- |
- SkDEBUGCODE(this->validate();) |
- |
- return fMatrixClipStack.count(); |
-} |
- |
-int SkMatrixClipStateMgr::save() { |
- SkDEBUGCODE(this->validate();) |
- |
- return this->MCStackPush(); |
-} |
- |
-int SkMatrixClipStateMgr::saveLayer(const SkRect* bounds, const SkPaint* paint, |
- SkCanvas::SaveFlags flags) { |
-#ifdef SK_DEBUG |
- if (fCurMCState->fIsSaveLayer) { |
- SkASSERT(0 == fSkipOffsets->count()); |
- } |
-#endif |
- |
- // Since the saveLayer call draws something we need to potentially dump |
- // out the MC state |
- SkDEBUGCODE(bool saved =) this->call(kOther_CallType); |
- |
- int result = this->MCStackPush(); |
- ++fCurMCState->fLayerID; |
- fCurMCState->fIsSaveLayer = true; |
- |
-#ifdef SK_DEBUG |
- if (saved) { |
- fCurMCState->fExpectedDepth++; // 1 for nesting save |
- } |
- fCurMCState->fExpectedDepth++; // 1 for saveLayer |
-#endif |
- |
- *fStateIDStack.append() = fCurOpenStateID; |
- fCurMCState->fSavedSkipOffsets = fSkipOffsets; |
- |
- // TODO: recycle these rather then new & deleting them on every saveLayer/ |
- // restore |
- fSkipOffsets = SkNEW(SkTDArray<int>); |
- |
- fPicRecord->recordSaveLayer(bounds, paint, flags); |
-#ifdef SK_DEBUG |
- fActualDepth++; |
-#endif |
- return result; |
-} |
- |
-void SkMatrixClipStateMgr::restore() { |
- SkDEBUGCODE(this->validate();) |
- |
- if (fCurMCState->fIsSaveLayer) { |
- if (fCurMCState->fHasOpen) { |
- fCurMCState->fHasOpen = false; |
- fPicRecord->recordRestore(); // Close the open block inside the saveLayer |
-#ifdef SK_DEBUG |
- SkASSERT(fActualDepth > 0); |
- fActualDepth--; |
-#endif |
- } else { |
- SkASSERT(0 == fSkipOffsets->count()); |
- } |
- |
- // 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 |
-#ifdef SK_DEBUG |
- SkASSERT(fActualDepth > 0); |
- fActualDepth--; |
-#endif |
- |
- SkASSERT(fStateIDStack.count() >= 1); |
- fCurOpenStateID = fStateIDStack[fStateIDStack.count()-1]; |
- fStateIDStack.pop(); |
- |
- SkASSERT(0 == fSkipOffsets->count()); |
- SkASSERT(NULL != fCurMCState->fSavedSkipOffsets); |
- |
- SkDELETE(fSkipOffsets); |
- fSkipOffsets = fCurMCState->fSavedSkipOffsets; |
- } |
- |
- bool prevHadOpen = fCurMCState->fHasOpen; |
- bool prevWasSaveLayer = fCurMCState->fIsSaveLayer; |
- |
- fCurMCState->~MatrixClipState(); // balanced in save() |
- fMatrixClipStack.pop_back(); |
- fCurMCState = (MatrixClipState*)fMatrixClipStack.back(); |
- |
- if (!prevWasSaveLayer) { |
- fCurMCState->fHasOpen = prevHadOpen; |
- } |
- |
- if (fCurMCState->fIsSaveLayer) { |
- if (0 != fSkipOffsets->count()) { |
- SkASSERT(fCurMCState->fHasOpen); |
- } |
- } |
- |
- SkDEBUGCODE(this->validate();) |
-} |
- |
-// kIdentityWideOpenStateID (0) is reserved for the identity/wide-open clip state |
-int32_t SkMatrixClipStateMgr::NewMCStateID() { |
- // TODO: guard against wrap around |
- // TODO: make uint32_t |
- static int32_t gMCStateID = kIdentityWideOpenStateID; |
- ++gMCStateID; |
- return gMCStateID; |
-} |
- |
-bool SkMatrixClipStateMgr::isNestingMCState(int stateID) { |
- return fStateIDStack.count() > 0 && fStateIDStack[fStateIDStack.count()-1] == fCurOpenStateID; |
-} |
- |
-bool SkMatrixClipStateMgr::call(CallType callType) { |
- SkDEBUGCODE(this->validate();) |
- |
- if (kMatrix_CallType == callType || kClip_CallType == callType) { |
- fCurMCState->fMCStateID = NewMCStateID(); |
- SkDEBUGCODE(this->validate();) |
- return false; |
- } |
- |
- SkASSERT(kOther_CallType == callType); |
- |
- if (fCurMCState->fMCStateID == fCurOpenStateID) { |
- // Required MC state is already active one - nothing to do |
- SkDEBUGCODE(this->validate();) |
- return false; |
- } |
- |
- if (kIdentityWideOpenStateID != fCurOpenStateID && |
- !this->isNestingMCState(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 |
- fCurMCState->fHasOpen = false; |
-#ifdef SK_DEBUG |
- SkASSERT(fActualDepth > 0); |
- fActualDepth--; |
-#endif |
- } |
- |
- // Install the required MC state as the active one |
- fCurOpenStateID = fCurMCState->fMCStateID; |
- |
- if (kIdentityWideOpenStateID == fCurOpenStateID) { |
- SkASSERT(0 == fActualDepth); |
- SkASSERT(!fCurMCState->fHasOpen); |
- SkASSERT(0 == fSkipOffsets->count()); |
- return false; |
- } |
- |
- SkASSERT(!fCurMCState->fHasOpen); |
- SkASSERT(0 == fSkipOffsets->count()); |
- fCurMCState->fHasOpen = true; |
- fPicRecord->recordSave(); |
-#ifdef SK_DEBUG |
- fActualDepth++; |
- SkASSERT(fActualDepth == fCurMCState->fExpectedDepth); |
-#endif |
- |
- // write out clips |
- 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.prev()) { |
- if (state->fIsSaveLayer) { |
- break; |
- } |
- } |
- |
- int curMatID; |
- |
- 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(); |
- curMatID = kIdentityMatID; |
- } 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); |
- |
- curMatID = state->fMatrixInfo->getID(this); |
- |
- // TODO: this assumes that, in the case of Save|SaveLayer when the SaveLayer |
- // doesn't save the clip, that the SaveLayer doesn't add any additional clip state. |
- // This assumption will be removed when we explicitly store the clip state in |
- // self-contained objects. It is valid for the small set of skps. |
- if (NULL != state->fPrev && state->fClipInfo == state->fPrev->fClipInfo) { |
- // By the above assumption the SaveLayer's MC state has already been |
- // written out by the prior Save so don't output it again. |
- state = (const MatrixClipState*) iter.next(); |
- } |
- } |
- |
- 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 |
- // write out the CTM here when the clip state is collapsed to a single path. |
- this->writeDeltaMat(curMatID, fCurMCState->fMatrixInfo->getID(this)); |
- } |
- |
- SkDEBUGCODE(this->validate();) |
- 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(int32_t peek = writer->readTAt<int32_t>((*fSkipOffsets)[i]);) |
- SkASSERT(-1 == peek); |
- writer->overwriteTAt<int32_t>((*fSkipOffsets)[i], restoreOffset); |
- } |
- |
- fSkipOffsets->rewind(); |
- SkASSERT(0 == fSkipOffsets->count()); |
-} |
- |
-void SkMatrixClipStateMgr::finish() { |
- if (kIdentityWideOpenStateID != fCurOpenStateID) { |
- fPicRecord->recordRestore(); // Close the open block |
- fCurMCState->fHasOpen = false; |
-#ifdef SK_DEBUG |
- SkASSERT(fActualDepth > 0); |
- fActualDepth--; |
-#endif |
- fCurOpenStateID = kIdentityWideOpenStateID; |
- SkASSERT(!fCurMCState->fHasOpen); |
- } |
-} |
- |
-#ifdef SK_DEBUG |
-void SkMatrixClipStateMgr::validate() { |
- if (fCurOpenStateID == fCurMCState->fMCStateID && !this->isNestingMCState(fCurOpenStateID)) { |
- // 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.prev()) { |
- if (NULL == state->fPrev || state->fPrev->fClipInfo != state->fClipInfo) { |
- clipCount += state->fClipInfo->numClips(); |
- } |
- if (state->fIsSaveLayer) { |
- break; |
- } |
- } |
- |
- SkASSERT(fSkipOffsets->count() == clipCount); |
- } |
-} |
-#endif |
- |
-int SkMatrixClipStateMgr::addRegionToDict(const SkRegion& region) { |
- int index = fRegionDict.count(); |
- *fRegionDict.append() = SkNEW(SkRegion(region)); |
- return index; |
-} |
- |
-int SkMatrixClipStateMgr::addMatToDict(const SkMatrix& mat) { |
- if (mat.isIdentity()) { |
- return kIdentityMatID; |
- } |
- |
- *fMatrixDict.append() = mat; |
- return fMatrixDict.count()-1; |
-} |