1105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com/*
2105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com * Copyright 2014 Google Inc.
3105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com *
4105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
5105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com * found in the LICENSE file.
6105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com */
7105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
8105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com#include "SkMatrixClipStateMgr.h"
9105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com#include "SkPictureRecord.h"
10105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
11877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.combool SkMatrixClipStateMgr::MatrixClipState::ClipInfo::clipPath(SkPictureRecord* picRecord,
12877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com                                                               const SkPath& path,
13877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com                                                               SkRegion::Op op,
14877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com                                                               bool doAA,
15c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org                                                               int matrixID) {
16105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    int pathID = picRecord->addPathToHeap(path);
17105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
189a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    ClipOp* newClip = fClips.append();
199a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    newClip->fClipType = kPath_ClipType;
209a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    newClip->fGeom.fPathID = pathID;
219a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    newClip->fOp = op;
229a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    newClip->fDoAA = doAA;
239a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    newClip->fMatrixID = matrixID;
24105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    return false;
25105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com}
26105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
27877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.combool SkMatrixClipStateMgr::MatrixClipState::ClipInfo::clipRegion(SkPictureRecord* picRecord,
289a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org                                                                 int regionID,
29877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com                                                                 SkRegion::Op op,
30c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org                                                                 int matrixID) {
319a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    ClipOp* newClip = fClips.append();
329a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    newClip->fClipType = kRegion_ClipType;
339a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    newClip->fGeom.fRegionID = regionID;
349a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    newClip->fOp = op;
359a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    newClip->fDoAA = true;      // not necessary but sanity preserving
369a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    newClip->fMatrixID = matrixID;
37105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    return false;
38105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com}
39105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
40c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.orgvoid SkMatrixClipStateMgr::writeDeltaMat(int currentMatID, int desiredMatID) {
41c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org    const SkMatrix& current = this->lookupMat(currentMatID);
42c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org    const SkMatrix& desired = this->lookupMat(desiredMatID);
43c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org
44105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    SkMatrix delta;
453cd6fdf64e7d4468ae589a2acab4c0fa7c1a9ae6robertphillips@google.com    bool result = current.invert(&delta);
463cd6fdf64e7d4468ae589a2acab4c0fa7c1a9ae6robertphillips@google.com    if (result) {
473cd6fdf64e7d4468ae589a2acab4c0fa7c1a9ae6robertphillips@google.com        delta.preConcat(desired);
483cd6fdf64e7d4468ae589a2acab4c0fa7c1a9ae6robertphillips@google.com    }
49c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org    fPicRecord->recordConcat(delta);
50105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com}
51105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
52105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com// Note: this only writes out the clips for the current save state. To get the
53105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com// entire clip stack requires iterating of the entire matrix/clip stack.
5422ef2c37e65e601ba78851e3dbb4ca7a0e4c7d61skia.committer@gmail.comvoid SkMatrixClipStateMgr::MatrixClipState::ClipInfo::writeClip(int* curMatID,
5592da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org                                                                SkMatrixClipStateMgr* mgr) {
56105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    for (int i = 0; i < fClips.count(); ++i) {
57105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        ClipOp& curClip = fClips[i];
58105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
59c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org        // TODO: use the matrix ID to skip writing the identity matrix
60c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org        // over and over, i.e.:
61c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org        //  if (*curMatID != curClip.fMatrixID) {
62c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org        //      mgr->writeDeltaMat...
63c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org        //      *curMatID...
64c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org        //  }
65c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org        // Right now this optimization would throw off the testing harness.
66105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        // TODO: right now we're writing out the delta matrix from the prior
67105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        // matrix state. This is a side-effect of writing out the entire
68105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        // clip stack and should be resolved when that is fixed.
69c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org        mgr->writeDeltaMat(*curMatID, curClip.fMatrixID);
70c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org        *curMatID = curClip.fMatrixID;
71877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com
72dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org        size_t offset = 0;
7392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
74105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        switch (curClip.fClipType) {
75105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        case kRect_ClipType:
7692da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org            offset = mgr->getPicRecord()->recordClipRect(curClip.fGeom.fRRect.rect(),
7792da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org                                                         curClip.fOp, curClip.fDoAA);
78105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com            break;
79105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        case kRRect_ClipType:
8092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org            offset = mgr->getPicRecord()->recordClipRRect(curClip.fGeom.fRRect, curClip.fOp,
8192da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org                                                         curClip.fDoAA);
82105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com            break;
83105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        case kPath_ClipType:
8492da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org            offset = mgr->getPicRecord()->recordClipPath(curClip.fGeom.fPathID, curClip.fOp,
8592da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org                                                         curClip.fDoAA);
86105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com            break;
879a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org        case kRegion_ClipType: {
889a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org            const SkRegion* region = mgr->lookupRegion(curClip.fGeom.fRegionID);
8992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org            offset = mgr->getPicRecord()->recordClipRegion(*region, curClip.fOp);
90105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com            break;
919a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org        }
92105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        default:
93105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com            SkASSERT(0);
94105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        }
95105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
9692da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        mgr->addClipOffset(offset);
97105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
98105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com}
99105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
100105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.comSkMatrixClipStateMgr::SkMatrixClipStateMgr()
101105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    : fPicRecord(NULL)
102877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com    , fMatrixClipStack(sizeof(MatrixClipState),
103877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com                       fMatrixClipStackStorage,
1043cd6fdf64e7d4468ae589a2acab4c0fa7c1a9ae6robertphillips@google.com                       sizeof(fMatrixClipStackStorage))
1053cd6fdf64e7d4468ae589a2acab4c0fa7c1a9ae6robertphillips@google.com    , fCurOpenStateID(kIdentityWideOpenStateID) {
106c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org
10792da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    fSkipOffsets = SkNEW(SkTDArray<int>);
10892da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
109c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org    // The first slot in the matrix dictionary is reserved for the identity matrix
110c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org    fMatrixDict.append()->reset();
111c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org
112105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    fCurMCState = (MatrixClipState*)fMatrixClipStack.push_back();
113105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    new (fCurMCState) MatrixClipState(NULL, 0);    // balanced in restore()
114fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com
115fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#ifdef SK_DEBUG
116fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    fActualDepth = 0;
117fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#endif
118105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com}
119105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
1209a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.orgSkMatrixClipStateMgr::~SkMatrixClipStateMgr() {
1219a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    for (int i = 0; i < fRegionDict.count(); ++i) {
1229a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org        SkDELETE(fRegionDict[i]);
1239a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    }
12492da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
12592da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    SkDELETE(fSkipOffsets);
1269a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org}
1279a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org
128105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
12992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.orgint SkMatrixClipStateMgr::MCStackPush(SkCanvas::SaveFlags flags) {
130105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    MatrixClipState* newTop = (MatrixClipState*)fMatrixClipStack.push_back();
131105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    new (newTop) MatrixClipState(fCurMCState, flags); // balanced in restore()
132105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    fCurMCState = newTop;
133105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
134105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    SkDEBUGCODE(this->validate();)
135105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
136105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    return fMatrixClipStack.count();
137105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com}
138105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
13992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.orgint SkMatrixClipStateMgr::save(SkCanvas::SaveFlags flags) {
14092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    SkDEBUGCODE(this->validate();)
14192da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
14292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    return this->MCStackPush(flags);
14392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org}
14492da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
145877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.comint SkMatrixClipStateMgr::saveLayer(const SkRect* bounds, const SkPaint* paint,
146105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com                                    SkCanvas::SaveFlags flags) {
147fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#ifdef SK_DEBUG
148fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    if (fCurMCState->fIsSaveLayer) {
149fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        SkASSERT(0 == fSkipOffsets->count());
150fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    }
151fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#endif
152fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com
15392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    // Since the saveLayer call draws something we need to potentially dump
15492da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    // out the MC state
155fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    SkDEBUGCODE(bool saved =) this->call(kOther_CallType);
15692da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
15792da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    int result = this->MCStackPush(flags);
158105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    ++fCurMCState->fLayerID;
159105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    fCurMCState->fIsSaveLayer = true;
160105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
161fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#ifdef SK_DEBUG
162fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    if (saved) {
163fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        fCurMCState->fExpectedDepth++; // 1 for nesting save
164fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    }
165fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    fCurMCState->fExpectedDepth++;   // 1 for saveLayer
166fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#endif
167fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com
1686c5f1fd66ca195daf04795907d04e1b0cbd3ecb6commit-bot@chromium.org    *fStateIDStack.append() = fCurOpenStateID;
16992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    fCurMCState->fSavedSkipOffsets = fSkipOffsets;
17092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
17192da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    // TODO: recycle these rather then new & deleting them on every saveLayer/
17292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    // restore
17392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    fSkipOffsets = SkNEW(SkTDArray<int>);
17492da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
1752a5cd60bfff32c92cf44a8cfc3e8c017b9aee456commit-bot@chromium.org    fPicRecord->recordSaveLayer(bounds, paint, flags | SkCanvas::kMatrixClip_SaveFlag);
176fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#ifdef SK_DEBUG
177fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    fActualDepth++;
178fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#endif
179105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    return result;
180105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com}
181105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
182105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.comvoid SkMatrixClipStateMgr::restore() {
183105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    SkDEBUGCODE(this->validate();)
184105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
185105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    if (fCurMCState->fIsSaveLayer) {
186fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        if (fCurMCState->fHasOpen) {
187fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com            fCurMCState->fHasOpen = false;
18892da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org            fPicRecord->recordRestore(); // Close the open block inside the saveLayer
189fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#ifdef SK_DEBUG
190fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com            SkASSERT(fActualDepth > 0);
191fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com            fActualDepth--;
192fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#endif
193fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        } else {
194fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com            SkASSERT(0 == fSkipOffsets->count());
195105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        }
196fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com
197105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        // The saveLayer's don't carry any matrix or clip state in the
198105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        // new scheme so make sure the saveLayer's recordRestore doesn't
199105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        // try to finalize them (i.e., fill in their skip offsets).
200105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        fPicRecord->recordRestore(false); // close of saveLayer
201fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#ifdef SK_DEBUG
202fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        SkASSERT(fActualDepth > 0);
203fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        fActualDepth--;
204fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#endif
205105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
2066c5f1fd66ca195daf04795907d04e1b0cbd3ecb6commit-bot@chromium.org        SkASSERT(fStateIDStack.count() >= 1);
2076c5f1fd66ca195daf04795907d04e1b0cbd3ecb6commit-bot@chromium.org        fCurOpenStateID = fStateIDStack[fStateIDStack.count()-1];
2086c5f1fd66ca195daf04795907d04e1b0cbd3ecb6commit-bot@chromium.org        fStateIDStack.pop();
209f7d08ed626a4825317405c3708cf2896509209d6robertphillips@google.com
21092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        SkASSERT(0 == fSkipOffsets->count());
21192da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        SkASSERT(NULL != fCurMCState->fSavedSkipOffsets);
21292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
21392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        SkDELETE(fSkipOffsets);
21492da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        fSkipOffsets = fCurMCState->fSavedSkipOffsets;
215105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
216105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
217fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    bool prevHadOpen = fCurMCState->fHasOpen;
218fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    bool prevWasSaveLayer = fCurMCState->fIsSaveLayer;
219fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com
220105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    fCurMCState->~MatrixClipState();       // balanced in save()
221105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    fMatrixClipStack.pop_back();
222105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    fCurMCState = (MatrixClipState*)fMatrixClipStack.back();
223105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
224fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    if (!prevWasSaveLayer) {
225fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        fCurMCState->fHasOpen = prevHadOpen;
226fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    }
227fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com
228fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    if (fCurMCState->fIsSaveLayer) {
229fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        if (0 != fSkipOffsets->count()) {
230fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com            SkASSERT(fCurMCState->fHasOpen);
231fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        }
232fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    }
233fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com
234105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    SkDEBUGCODE(this->validate();)
235105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com}
236105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
237105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com// kIdentityWideOpenStateID (0) is reserved for the identity/wide-open clip state
238105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.comint32_t SkMatrixClipStateMgr::NewMCStateID() {
239105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    // TODO: guard against wrap around
240105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    // TODO: make uint32_t
241105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    static int32_t gMCStateID = kIdentityWideOpenStateID;
242105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    ++gMCStateID;
243105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    return gMCStateID;
244105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com}
245105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
2466c5f1fd66ca195daf04795907d04e1b0cbd3ecb6commit-bot@chromium.orgbool SkMatrixClipStateMgr::isNestingMCState(int stateID) {
2476c5f1fd66ca195daf04795907d04e1b0cbd3ecb6commit-bot@chromium.org    return fStateIDStack.count() > 0 && fStateIDStack[fStateIDStack.count()-1] == fCurOpenStateID;
248fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com}
249fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com
250105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.combool SkMatrixClipStateMgr::call(CallType callType) {
251105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    SkDEBUGCODE(this->validate();)
252105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
253105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    if (kMatrix_CallType == callType || kClip_CallType == callType) {
254105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        fCurMCState->fMCStateID = NewMCStateID();
255105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        SkDEBUGCODE(this->validate();)
256105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        return false;
257105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
258105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
259105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    SkASSERT(kOther_CallType == callType);
260105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
261105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    if (fCurMCState->fMCStateID == fCurOpenStateID) {
262105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        // Required MC state is already active one - nothing to do
263105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        SkDEBUGCODE(this->validate();)
264105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        return false;
265105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
266105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
2677911ade991336adab70a99f50fbe9dc5ef79d0a0skia.committer@gmail.com    if (kIdentityWideOpenStateID != fCurOpenStateID &&
2686c5f1fd66ca195daf04795907d04e1b0cbd3ecb6commit-bot@chromium.org        !this->isNestingMCState(fCurOpenStateID)) {
26992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        // Don't write a restore if the open state is one in which a saveLayer
27092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        // is nested. The save after the saveLayer's restore will close it.
271105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        fPicRecord->recordRestore();    // Close the open block
272fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        fCurMCState->fHasOpen = false;
273fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#ifdef SK_DEBUG
274fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        SkASSERT(fActualDepth > 0);
275fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        fActualDepth--;
276fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#endif
277105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
278877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com
279105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    // Install the required MC state as the active one
280105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    fCurOpenStateID = fCurMCState->fMCStateID;
281105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
282fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    if (kIdentityWideOpenStateID == fCurOpenStateID) {
283fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        SkASSERT(0 == fActualDepth);
284fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        SkASSERT(!fCurMCState->fHasOpen);
285fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        SkASSERT(0 == fSkipOffsets->count());
286fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        return false;
287fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    }
288fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com
289fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    SkASSERT(!fCurMCState->fHasOpen);
290fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    SkASSERT(0 == fSkipOffsets->count());
291fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    fCurMCState->fHasOpen = true;
292105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    fPicRecord->recordSave(SkCanvas::kMatrixClip_SaveFlag);
293fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#ifdef SK_DEBUG
294fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    fActualDepth++;
295fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    SkASSERT(fActualDepth == fCurMCState->fExpectedDepth);
296fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#endif
297105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
298105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    // write out clips
29992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    SkDeque::Iter iter(fMatrixClipStack, SkDeque::Iter::kBack_IterStart);
30092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    const MatrixClipState* state;
30192da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    // Loop back across the MC states until the last saveLayer. The MC
30292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    // state in front of the saveLayer has already been written out.
30392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    for (state = (const MatrixClipState*) iter.prev();
3041cb6d1a1fd11b23aca42dcb8453e6816836b7b6fcommit-bot@chromium.org         state != NULL;
30592da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org         state = (const MatrixClipState*) iter.prev()) {
30692da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        if (state->fIsSaveLayer) {
30792da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org            break;
30892da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        }
30992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    }
31092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
311fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    int curMatID;
312fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com
31392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    if (NULL == state) {
31492da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        // There was no saveLayer in the MC stack so we need to output them all
31592da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        iter.reset(fMatrixClipStack, SkDeque::Iter::kFront_IterStart);
31692da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        state = (const MatrixClipState*) iter.next();
317fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        curMatID = kIdentityMatID;
31892da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    } else {
31992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        // SkDeque's iterators actually return the previous location so we
32092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        // need to reverse and go forward one to get back on track.
321c05d2859e10f4e1fb0c6486eebfbe88801202648skia.committer@gmail.com        iter.next();
322c05d2859e10f4e1fb0c6486eebfbe88801202648skia.committer@gmail.com        SkDEBUGCODE(const MatrixClipState* test = (const MatrixClipState*)) iter.next();
32392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        SkASSERT(test == state);
324fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com
325fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        curMatID = state->fMatrixInfo->getID(this);
326fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com
327fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        // TODO: this assumes that, in the case of Save|SaveLayer when the SaveLayer
328fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        // doesn't save the clip, that the SaveLayer doesn't add any additional clip state.
3297911ade991336adab70a99f50fbe9dc5ef79d0a0skia.committer@gmail.com        // This assumption will be removed when we explicitly store the clip state in
330fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        // self-contained objects. It is valid for the small set of skps.
331fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        if (NULL != state->fPrev && state->fClipInfo == state->fPrev->fClipInfo) {
332fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com            // By the above assumption the SaveLayer's MC state has already been
333fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com            // written out by the prior Save so don't output it again.
334fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com            state = (const MatrixClipState*) iter.next();
335fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        }
33692da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    }
33792da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
33892da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    for ( ; state != NULL; state = (const MatrixClipState*) iter.next()) {
33992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org         state->fClipInfo->writeClip(&curMatID, this);
340105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
341105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
342105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    // write out matrix
34392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    // TODO: this test isn't quite right. It should be:
34492da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    //   if (curMatID != fCurMCState->fMatrixInfo->getID(this)) {
34592da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    // but right now the testing harness always expects a matrix if
34692da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    // the matrices are non-I
347c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org    if (kIdentityMatID != fCurMCState->fMatrixInfo->getID(this)) {
348877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com        // TODO: writing out the delta matrix here is an artifact of the writing
349877c44956dceff038c0e315c8d311b0d581f2680skia.committer@gmail.com        // out of the entire clip stack (with its matrices). Ultimately we will
350105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        // write out the CTM here when the clip state is collapsed to a single path.
351c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org        this->writeDeltaMat(curMatID, fCurMCState->fMatrixInfo->getID(this));
352105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
353105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
354105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    SkDEBUGCODE(this->validate();)
355105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    return true;
356105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com}
357105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
35892da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org// Fill in the skip offsets for all the clips written in the current block
35992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.orgvoid SkMatrixClipStateMgr::fillInSkips(SkWriter32* writer, int32_t restoreOffset) {
36092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    for (int i = 0; i < fSkipOffsets->count(); ++i) {
36192da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        SkDEBUGCODE(int32_t peek = writer->readTAt<int32_t>((*fSkipOffsets)[i]);)
36292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        SkASSERT(-1 == peek);
36392da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        writer->overwriteTAt<int32_t>((*fSkipOffsets)[i], restoreOffset);
36492da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    }
36592da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
36692da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org    fSkipOffsets->rewind();
367fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com    SkASSERT(0 == fSkipOffsets->count());
36892da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org}
36992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
370105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.comvoid SkMatrixClipStateMgr::finish() {
371105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    if (kIdentityWideOpenStateID != fCurOpenStateID) {
372105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        fPicRecord->recordRestore();    // Close the open block
373fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        fCurMCState->fHasOpen = false;
374fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#ifdef SK_DEBUG
375fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        SkASSERT(fActualDepth > 0);
376fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        fActualDepth--;
377fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com#endif
378105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        fCurOpenStateID = kIdentityWideOpenStateID;
379fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com        SkASSERT(!fCurMCState->fHasOpen);
380105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
381105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com}
382105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com
383105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com#ifdef SK_DEBUG
384105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.comvoid SkMatrixClipStateMgr::validate() {
3856c5f1fd66ca195daf04795907d04e1b0cbd3ecb6commit-bot@chromium.org    if (fCurOpenStateID == fCurMCState->fMCStateID && !this->isNestingMCState(fCurOpenStateID)) {
38692da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        // The current state is the active one so it should have a skip
38792da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        // offset for each clip
38892da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        SkDeque::Iter iter(fMatrixClipStack, SkDeque::Iter::kBack_IterStart);
38992da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        int clipCount = 0;
39092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        for (const MatrixClipState* state = (const MatrixClipState*) iter.prev();
391105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com             state != NULL;
39292da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org             state = (const MatrixClipState*) iter.prev()) {
393fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com            if (NULL == state->fPrev || state->fPrev->fClipInfo != state->fClipInfo) {
394fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com                clipCount += state->fClipInfo->numClips();
395fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com            }
396fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com            if (state->fIsSaveLayer) {
397fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com                break;
398fc4ded9f4aeeefbbd0c22d665589ea017f7a9aedrobertphillips@google.com            }
399105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com        }
40092da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org
40192da60cd6339de32b2d8b19420f511208adf4187commit-bot@chromium.org        SkASSERT(fSkipOffsets->count() == clipCount);
402105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com    }
403105a4a584c4c2c84c24e102112326b15683673f5robertphillips@google.com}
4043cd6fdf64e7d4468ae589a2acab4c0fa7c1a9ae6robertphillips@google.com#endif
405c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org
4069a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.orgint SkMatrixClipStateMgr::addRegionToDict(const SkRegion& region) {
4079a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    int index = fRegionDict.count();
4089a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    *fRegionDict.append() = SkNEW(SkRegion(region));
4099a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org    return index;
4109a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org}
4119a67a7e2a0b53bb9092e2570ac6ea6a68b7371b0commit-bot@chromium.org
412c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.orgint SkMatrixClipStateMgr::addMatToDict(const SkMatrix& mat) {
413c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org    if (mat.isIdentity()) {
414c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org        return kIdentityMatID;
415c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org    }
416c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org
417c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org    *fMatrixDict.append() = mat;
418c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org    return fMatrixDict.count()-1;
419c5dada85e88298399a15d7347954f445ee798e19commit-bot@chromium.org}
420