Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(174)

Side by Side Diff: src/core/SkMatrixClipStateMgr.h

Issue 453133003: Remove Matrix/Clip State collapse code (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Removed blank lines Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gyp/core.gypi ('k') | src/core/SkMatrixClipStateMgr.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 #ifndef SkMatrixClipStateMgr_DEFINED
8 #define SkMatrixClipStateMgr_DEFINED
9
10 #include "SkCanvas.h"
11 #include "SkMatrix.h"
12 #include "SkRegion.h"
13 #include "SkRRect.h"
14 #include "SkTypes.h"
15 #include "SkTDArray.h"
16
17 class SkPictureRecord;
18 class SkWriter32;
19
20 // The SkMatrixClipStateMgr collapses the matrix/clip state of an SkPicture into
21 // a series of save/restore blocks of consistent matrix clip state, e.g.:
22 //
23 // save
24 // clip(s)
25 // concat
26 // ... draw ops ...
27 // restore
28 //
29 // SaveLayers simply add another level, e.g.:
30 //
31 // save
32 // clip(s)
33 // concat
34 // ... draw ops ...
35 // saveLayer
36 // save
37 // clip(s)
38 // concat
39 // ... draw ops ...
40 // restore
41 // restore
42 // restore
43 //
44 // As a side effect of this process all saves and saveLayers will become
45 // kMatrixClip_SaveFlag style saves/saveLayers.
46
47 // The SkMatrixClipStateMgr works by intercepting all the save*, restore, clip*,
48 // and matrix calls sent to SkCanvas in order to track the current matrix/clip
49 // state. All the other canvas calls get funnelled into a generic "call" entry
50 // point that signals that a state block is required.
51 class SkMatrixClipStateMgr {
52 public:
53 static const int32_t kIdentityWideOpenStateID = 0;
54 static const int kIdentityMatID = 0;
55
56 class MatrixClipState : SkNoncopyable {
57 public:
58 class MatrixInfo {
59 public:
60 void reset() {
61 fMatrixID = kIdentityMatID;
62 fMatrix.reset();
63 }
64
65 void preTranslate(SkScalar dx, SkScalar dy) {
66 fMatrixID = -1;
67 fMatrix.preTranslate(dx, dy);
68 }
69
70 void preScale(SkScalar sx, SkScalar sy) {
71 fMatrixID = -1;
72 fMatrix.preScale(sx, sy);
73 }
74
75 void preRotate(SkScalar degrees) {
76 fMatrixID = -1;
77 fMatrix.preRotate(degrees);
78 }
79
80 void preSkew(SkScalar sx, SkScalar sy) {
81 fMatrixID = -1;
82 fMatrix.preSkew(sx, sy);
83 }
84
85 void preConcat(const SkMatrix& matrix) {
86 fMatrixID = -1;
87 fMatrix.preConcat(matrix);
88 }
89
90 void setMatrix(const SkMatrix& matrix) {
91 fMatrixID = -1;
92 fMatrix = matrix;
93 }
94
95 int getID(SkMatrixClipStateMgr* mgr) {
96 if (fMatrixID >= 0) {
97 return fMatrixID;
98 }
99
100 fMatrixID = mgr->addMatToDict(fMatrix);
101 return fMatrixID;
102 }
103
104 private:
105 SkMatrix fMatrix;
106 int fMatrixID;
107
108 typedef SkNoncopyable INHERITED;
109 };
110
111 class ClipInfo : SkNoncopyable {
112 public:
113 ClipInfo() {}
114
115 bool clipRect(const SkRect& rect,
116 SkRegion::Op op,
117 bool doAA,
118 int matrixID) {
119 ClipOp* newClip = fClips.append();
120 newClip->fClipType = kRect_ClipType;
121 newClip->fGeom.fRRect.setRect(rect); // storing the clipRect i n the RRect
122 newClip->fOp = op;
123 newClip->fDoAA = doAA;
124 newClip->fMatrixID = matrixID;
125 return false;
126 }
127
128 bool clipRRect(const SkRRect& rrect,
129 SkRegion::Op op,
130 bool doAA,
131 int matrixID) {
132 ClipOp* newClip = fClips.append();
133 newClip->fClipType = kRRect_ClipType;
134 newClip->fGeom.fRRect = rrect;
135 newClip->fOp = op;
136 newClip->fDoAA = doAA;
137 newClip->fMatrixID = matrixID;
138 return false;
139 }
140
141 bool clipPath(SkPictureRecord* picRecord,
142 const SkPath& path,
143 SkRegion::Op op,
144 bool doAA,
145 int matrixID);
146 bool clipRegion(SkPictureRecord* picRecord,
147 int regionID,
148 SkRegion::Op op,
149 int matrixID);
150 void writeClip(int* curMatID, SkMatrixClipStateMgr* mgr);
151
152 SkDEBUGCODE(int numClips() const { return fClips.count(); })
153
154 private:
155 enum ClipType {
156 kRect_ClipType,
157 kRRect_ClipType,
158 kPath_ClipType,
159 kRegion_ClipType
160 };
161
162 class ClipOp {
163 public:
164 ClipType fClipType;
165
166 union {
167 SkRRect fRRect; // also stores clip rect
168 int fPathID;
169 int fRegionID;
170 } fGeom;
171
172 bool fDoAA;
173 SkRegion::Op fOp;
174
175 // The CTM in effect when this clip call was issued
176 int fMatrixID;
177 };
178
179 SkTDArray<ClipOp> fClips;
180
181 typedef SkNoncopyable INHERITED;
182 };
183
184 MatrixClipState(MatrixClipState* prev)
185 : fPrev(prev)
186 {
187 fHasOpen = false;
188
189 if (NULL == prev) {
190 fLayerID = 0;
191
192 fMatrixInfoStorage.reset();
193 fMatrixInfo = &fMatrixInfoStorage;
194 fClipInfo = &fClipInfoStorage; // ctor handles init of fClipInf oStorage
195
196 // The identity/wide-open-clip state is current by default
197 fMCStateID = kIdentityWideOpenStateID;
198 #ifdef SK_DEBUG
199 fExpectedDepth = 1;
200 #endif
201 }
202 else {
203 fLayerID = prev->fLayerID;
204
205 fMatrixInfoStorage = *prev->fMatrixInfo;
206 fMatrixInfo = &fMatrixInfoStorage;
207
208 // We don't copy the ClipOps of the previous clip states
209 fClipInfo = &fClipInfoStorage;
210
211 // Initially a new save/saveLayer represents the same MC state
212 // as its predecessor.
213 fMCStateID = prev->fMCStateID;
214 #ifdef SK_DEBUG
215 fExpectedDepth = prev->fExpectedDepth;
216 #endif
217 }
218
219 fIsSaveLayer = false;
220 }
221
222 MatrixInfo* fMatrixInfo;
223 MatrixInfo fMatrixInfoStorage;
224
225 ClipInfo* fClipInfo;
226 ClipInfo fClipInfoStorage;
227
228 // Tracks the current depth of saveLayers to support the isDrawingToLaye r call
229 int fLayerID;
230 // Does this MC state represent a saveLayer call?
231 bool fIsSaveLayer;
232
233 // The next field is only valid when fIsSaveLayer is set.
234 SkTDArray<int>* fSavedSkipOffsets;
235
236 // Does the MC state have an open block in the skp?
237 bool fHasOpen;
238
239 MatrixClipState* fPrev;
240
241 #ifdef SK_DEBUG
242 int fExpectedDepth; // debugging aid
243 #endif
244
245 int32_t fMCStateID;
246 };
247
248 enum CallType {
249 kMatrix_CallType,
250 kClip_CallType,
251 kOther_CallType
252 };
253
254 SkMatrixClipStateMgr();
255 ~SkMatrixClipStateMgr();
256
257 void init(SkPictureRecord* picRecord) {
258 // Note: we're not taking a ref here. It is expected that the SkMatrixCl ipStateMgr
259 // is owned by the SkPictureRecord object
260 fPicRecord = picRecord;
261 }
262
263 SkPictureRecord* getPicRecord() { return fPicRecord; }
264
265 // TODO: need to override canvas' getSaveCount. Right now we pass the
266 // save* and restore calls on to the base SkCanvas in SkPictureRecord but
267 // this duplicates effort.
268 int getSaveCount() const { return fMatrixClipStack.count(); }
269
270 int save();
271
272 int saveLayer(const SkRect* bounds, const SkPaint* paint, SkCanvas::SaveFlag s flags);
273
274 bool isDrawingToLayer() const {
275 return fCurMCState->fLayerID > 0;
276 }
277
278 void restore();
279
280 void translate(SkScalar dx, SkScalar dy) {
281 this->call(kMatrix_CallType);
282 fCurMCState->fMatrixInfo->preTranslate(dx, dy);
283 }
284
285 void scale(SkScalar sx, SkScalar sy) {
286 this->call(kMatrix_CallType);
287 fCurMCState->fMatrixInfo->preScale(sx, sy);
288 }
289
290 void rotate(SkScalar degrees) {
291 this->call(kMatrix_CallType);
292 fCurMCState->fMatrixInfo->preRotate(degrees);
293 }
294
295 void skew(SkScalar sx, SkScalar sy) {
296 this->call(kMatrix_CallType);
297 fCurMCState->fMatrixInfo->preSkew(sx, sy);
298 }
299
300 void concat(const SkMatrix& matrix) {
301 this->call(kMatrix_CallType);
302 fCurMCState->fMatrixInfo->preConcat(matrix);
303 }
304
305 void setMatrix(const SkMatrix& matrix) {
306 this->call(kMatrix_CallType);
307 fCurMCState->fMatrixInfo->setMatrix(matrix);
308 }
309
310 bool clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
311 this->call(SkMatrixClipStateMgr::kClip_CallType);
312 return fCurMCState->fClipInfo->clipRect(rect, op, doAA,
313 fCurMCState->fMatrixInfo->getID( this));
314 }
315
316 bool clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
317 this->call(SkMatrixClipStateMgr::kClip_CallType);
318 return fCurMCState->fClipInfo->clipRRect(rrect, op, doAA,
319 fCurMCState->fMatrixInfo->getID (this));
320 }
321
322 bool clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
323 this->call(SkMatrixClipStateMgr::kClip_CallType);
324 return fCurMCState->fClipInfo->clipPath(fPicRecord, path, op, doAA,
325 fCurMCState->fMatrixInfo->getID( this));
326 }
327
328 bool clipRegion(const SkRegion& region, SkRegion::Op op) {
329 this->call(SkMatrixClipStateMgr::kClip_CallType);
330 int regionID = this->addRegionToDict(region);
331 return fCurMCState->fClipInfo->clipRegion(fPicRecord, regionID, op,
332 fCurMCState->fMatrixInfo->getI D(this));
333 }
334
335 bool call(CallType callType);
336
337 void fillInSkips(SkWriter32* writer, int32_t restoreOffset);
338
339 void finish();
340
341 protected:
342 SkPictureRecord* fPicRecord;
343
344 uint32_t fMatrixClipStackStorage[43]; // sized to fit 2 clip states
345 SkDeque fMatrixClipStack;
346 MatrixClipState* fCurMCState;
347
348 // This dictionary doesn't actually de-duplicate the matrices (except for th e
349 // identity matrix). It merely stores the matrices and allows them to be loo ked
350 // up by ID later. The de-duplication mainly falls upon the matrix/clip stac k
351 // which stores the ID so a revisited clip/matrix (via popping the stack) wi ll
352 // use the same ID.
353 SkTDArray<SkMatrix> fMatrixDict;
354
355 SkTDArray<SkRegion*> fRegionDict;
356
357 // The MCStateID of the state currently in effect in the byte stream. 0 if n one.
358 int32_t fCurOpenStateID;
359 // The skip offsets for the current open state. These are the locations in t he
360 // skp that must be filled in when the current open state is closed. These a re
361 // here rather then distributed across the MatrixClipState's because saveLay ers
362 // can cause MC states to be nested.
363 SkTDArray<int32_t> *fSkipOffsets; // TODO: should we store u32 or size_t i nstead?
364
365 SkDEBUGCODE(void validate();)
366
367 int MCStackPush();
368
369 void addClipOffset(size_t offset) {
370 SkASSERT(NULL != fSkipOffsets);
371 SkASSERT(kIdentityWideOpenStateID != fCurOpenStateID);
372 SkASSERT(fCurMCState->fHasOpen);
373 SkASSERT(!fCurMCState->fIsSaveLayer);
374
375 *fSkipOffsets->append() = SkToS32(offset);
376 }
377
378 void writeDeltaMat(int currentMatID, int desiredMatID);
379 static int32_t NewMCStateID();
380
381 int addRegionToDict(const SkRegion& region);
382 const SkRegion* lookupRegion(int index) {
383 SkASSERT(index >= 0 && index < fRegionDict.count());
384 return fRegionDict[index];
385 }
386
387 // TODO: add stats to check if the dictionary really does
388 // reduce the size of the SkPicture.
389 int addMatToDict(const SkMatrix& mat);
390 const SkMatrix& lookupMat(int index) {
391 SkASSERT(index >= 0 && index < fMatrixDict.count());
392 return fMatrixDict[index];
393 }
394
395 bool isNestingMCState(int stateID);
396
397 #ifdef SK_DEBUG
398 int fActualDepth;
399 #endif
400
401 // save layers are nested within a specific MC state. This stack tracks
402 // the nesting MC state's ID as save layers are pushed and popped.
403 SkTDArray<int> fStateIDStack;
404 };
405
406 #endif
OLDNEW
« no previous file with comments | « gyp/core.gypi ('k') | src/core/SkMatrixClipStateMgr.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698