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

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

Issue 137093004: Collapse matrix & clip stack in PictureRecord (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Fixed over application of SK_ prefix Created 6 years, 10 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 | Annotate | Revision Log
« 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')
Property Changes:
Added: svn:eol-style
+ LF
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 "SkTArray.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
55 class MatrixClipState {
56 public:
57 class MatrixInfo {
58 public:
59 SkMatrix fMatrix;
60 // TODO: add an internal dictionary and an ID here
61 };
62
63 class ClipInfo : public SkNoncopyable {
64 public:
65 ClipInfo() {}
66
67 bool clipRect(const SkRect& rect,
68 SkRegion::Op op,
69 bool doAA,
70 const SkMatrix& matrix) {
71 ClipOp& newClip = fClips.push_back();
72 newClip.fClipType = kRect_ClipType;
73 newClip.fGeom.fRRect.setRect(rect); // storing the clipRect in the RRect
74 newClip.fOp = op;
75 newClip.fDoAA = doAA;
76 newClip.fMatrix = matrix;
77 newClip.fOffset = kInvalidJumpOffset;
78 return false;
79 }
80
81 bool clipRRect(const SkRRect& rrect,
82 SkRegion::Op op,
83 bool doAA,
84 const SkMatrix& matrix) {
85 ClipOp& newClip = fClips.push_back();
86 newClip.fClipType = kRRect_ClipType;
87 newClip.fGeom.fRRect = rrect;
88 newClip.fOp = op;
89 newClip.fDoAA = doAA;
90 newClip.fMatrix = matrix;
91 newClip.fOffset = kInvalidJumpOffset;
92 return false;
93 }
94
95 bool clipPath(SkPictureRecord* picRecord,
96 const SkPath& path,
97 SkRegion::Op op,
98 bool doAA,
99 const SkMatrix& matrix);
100 bool clipRegion(SkPictureRecord* picRecord,
101 const SkRegion& region,
102 SkRegion::Op op,
103 const SkMatrix& matrix);
104 void writeClip(SkMatrix* curMat,
105 SkPictureRecord* picRecord,
106 bool* overrideFirstOp);
107 void fillInSkips(SkWriter32* writer, int32_t restoreOffset);
108
109 #ifdef SK_DEBUG
110 void checkOffsetNotEqual(int32_t offset) {
111 for (int i = 0; i < fClips.count(); ++i) {
112 ClipOp& curClip = fClips[i];
113 SkASSERT(offset != curClip.fOffset);
114 }
115 }
116 #endif
117 private:
118 enum ClipType {
119 kRect_ClipType,
120 kRRect_ClipType,
121 kPath_ClipType,
122 kRegion_ClipType
123 };
124
125 static const int kInvalidJumpOffset = -1;
126
127 class ClipOp {
128 public:
129 ClipOp() {}
130 ~ClipOp() {
131 if (kRegion_ClipType == fClipType) {
132 SkDELETE(fGeom.fRegion);
133 }
134 }
135
136 ClipType fClipType;
137
138 union {
139 SkRRect fRRect; // also stores clipRect
140 int fPathID;
141 // TODO: add internal dictionary of regions
142 // This parameter forces us to have a dtor and thus use
143 // SkTArray rather then SkTDArray!
144 const SkRegion* fRegion;
145 } fGeom;
146
147 bool fDoAA;
148 SkRegion::Op fOp;
149
150 // The CTM in effect when this clip call was issued
151 // TODO: add an internal dictionary and replace with ID
152 SkMatrix fMatrix;
153
154 // The offset of this clipOp's "jump-to-offset" location in the skp.
155 // -1 means the offset hasn't been written.
156 int32_t fOffset;
157 };
158
159 SkTArray<ClipOp> fClips;
160
161 typedef SkNoncopyable INHERITED;
162 };
163
164 MatrixClipState(MatrixClipState* prev, int flags)
165 #ifdef SK_DEBUG
166 : fPrev(prev)
167 #endif
168 {
169 if (NULL == prev) {
170 fLayerID = 0;
171
172 fMatrixInfoStorage.fMatrix.reset();
173 fMatrixInfo = &fMatrixInfoStorage;
174 fClipInfo = &fClipInfoStorage; // ctor handles init of fClipInf oStorage
175
176 // The identity/wide-open-clip state is current by default
177 fMCStateID = kIdentityWideOpenStateID;
178 }
179 else {
180 fLayerID = prev->fLayerID;
181
182 if (flags & SkCanvas::kMatrix_SaveFlag) {
183 fMatrixInfoStorage = *prev->fMatrixInfo;
184 fMatrixInfo = &fMatrixInfoStorage;
185 } else {
186 fMatrixInfo = prev->fMatrixInfo;
187 }
188
189 if (flags & SkCanvas::kClip_SaveFlag) {
190 // We don't copy the ClipOps of the previous clip states
191 fClipInfo = &fClipInfoStorage;
192 } else {
193 fClipInfo = prev->fClipInfo;
194 }
195
196 // Initially a new save/saveLayer represents the same MC state
197 // as its predecessor.
198 fMCStateID = prev->fMCStateID;
199 }
200
201 fIsSaveLayer = false;
202 }
203
204 MatrixInfo* fMatrixInfo;
205 MatrixInfo fMatrixInfoStorage;
206
207 ClipInfo* fClipInfo;
208 ClipInfo fClipInfoStorage;
209
210 // Tracks the current depth of saveLayers to support the isDrawingToLaye r call
211 int fLayerID;
212 // Does this MC state represent a saveLayer call?
213 bool fIsSaveLayer;
214
215 // The next two fields are only valid when fIsSaveLayer is set.
216 int32_t fSaveLayerBaseStateID;
217 bool fSaveLayerBracketed;
218
219 #ifdef SK_DEBUG
220 MatrixClipState* fPrev; // debugging aid
221 #endif
222
223 int32_t fMCStateID;
224 };
225
226 enum CallType {
227 kMatrix_CallType,
228 kClip_CallType,
229 kOther_CallType
230 };
231
232 SkMatrixClipStateMgr();
233
234 void init(SkPictureRecord* picRecord) {
235 // Note: we're not taking a ref here. It is expected that the SkMatrixCl ipStateMgr
236 // is owned by the SkPictureRecord object
237 fPicRecord = picRecord;
238 }
239
240 // TODO: need to override canvas' getSaveCount. Right now we pass the
241 // save* and restore calls on to the base SkCanvas in SkPictureRecord but
242 // this duplicates effort.
243 int getSaveCount() const { return fMatrixClipStack.count(); }
244
245 int save(SkCanvas::SaveFlags flags);
246
247 int saveLayer(const SkRect* bounds, const SkPaint* paint, SkCanvas::SaveFlag s flags);
248
249 bool isDrawingToLayer() const {
250 return fCurMCState->fLayerID > 0;
251 }
252
253 void restore();
254
255 bool translate(SkScalar dx, SkScalar dy) {
256 this->call(kMatrix_CallType);
257 return fCurMCState->fMatrixInfo->fMatrix.preTranslate(dx, dy);
258 }
259
260 bool scale(SkScalar sx, SkScalar sy) {
261 this->call(kMatrix_CallType);
262 return fCurMCState->fMatrixInfo->fMatrix.preScale(sx, sy);
263 }
264
265 bool rotate(SkScalar degrees) {
266 this->call(kMatrix_CallType);
267 return fCurMCState->fMatrixInfo->fMatrix.preRotate(degrees);
268 }
269
270 bool skew(SkScalar sx, SkScalar sy) {
271 this->call(kMatrix_CallType);
272 return fCurMCState->fMatrixInfo->fMatrix.preSkew(sx, sy);
273 }
274
275 bool concat(const SkMatrix& matrix) {
276 this->call(kMatrix_CallType);
277 return fCurMCState->fMatrixInfo->fMatrix.preConcat(matrix);
278 }
279
280 void setMatrix(const SkMatrix& matrix) {
281 this->call(kMatrix_CallType);
282 fCurMCState->fMatrixInfo->fMatrix = matrix;
283 }
284
285 bool clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
286 this->call(SkMatrixClipStateMgr::kClip_CallType);
287 return fCurMCState->fClipInfo->clipRect(rect, op, doAA,
288 fCurMCState->fMatrixInfo->fMatri x);
289 }
290
291 bool clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
292 this->call(SkMatrixClipStateMgr::kClip_CallType);
293 return fCurMCState->fClipInfo->clipRRect(rrect, op, doAA,
294 fCurMCState->fMatrixInfo->fMatr ix);
295 }
296
297 bool clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
298 this->call(SkMatrixClipStateMgr::kClip_CallType);
299 return fCurMCState->fClipInfo->clipPath(fPicRecord, path, op, doAA,
300 fCurMCState->fMatrixInfo->fMatri x);
301 }
302
303 bool clipRegion(const SkRegion& region, SkRegion::Op op) {
304 this->call(SkMatrixClipStateMgr::kClip_CallType);
305 return fCurMCState->fClipInfo->clipRegion(fPicRecord, region, op,
306 fCurMCState->fMatrixInfo->fMat rix);
307 }
308
309 bool call(CallType callType);
310
311 void fillInSkips(SkWriter32* writer, int32_t restoreOffset) {
312 // Since we write out the entire clip stack at each block start we
313 // need to update the skips for the entire stack each time too.
314 SkDeque::F2BIter iter(fMatrixClipStack);
315
316 for (const MatrixClipState* state = (const MatrixClipState*) iter.next() ;
317 state != NULL;
318 state = (const MatrixClipState*) iter.next()) {
319 state->fClipInfo->fillInSkips(writer, restoreOffset);
320 }
321 }
322
323 void finish();
324
325 protected:
326 SkPictureRecord* fPicRecord;
327
328 uint32_t fMatrixClipStackStorage[43]; // sized to fit 2 clip states
329 SkDeque fMatrixClipStack;
330 MatrixClipState* fCurMCState;
331
332 // The MCStateID of the state currently in effect in the byte stream. 0 if n one.
333 int32_t fCurOpenStateID;
334
335 SkDEBUGCODE(void validate();)
336
337 static void WriteDeltaMat(SkPictureRecord* picRecord,
338 const SkMatrix& current,
339 const SkMatrix& desired);
340 static int32_t NewMCStateID();
341 };
342
343 #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