OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 #ifndef SkMatrixClipStateMgr_DEFINED | 7 #ifndef SkMatrixClipStateMgr_DEFINED |
8 #define SkMatrixClipStateMgr_DEFINED | 8 #define SkMatrixClipStateMgr_DEFINED |
9 | 9 |
10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
11 #include "SkMatrix.h" | 11 #include "SkMatrix.h" |
12 #include "SkRegion.h" | 12 #include "SkRegion.h" |
13 #include "SkRRect.h" | 13 #include "SkRRect.h" |
14 #include "SkTypes.h" | 14 #include "SkTypes.h" |
15 #include "SkTArray.h" | |
16 #include "SkTDArray.h" | 15 #include "SkTDArray.h" |
17 | 16 |
18 class SkPictureRecord; | 17 class SkPictureRecord; |
19 class SkWriter32; | 18 class SkWriter32; |
20 | 19 |
21 // The SkMatrixClipStateMgr collapses the matrix/clip state of an SkPicture into | 20 // The SkMatrixClipStateMgr collapses the matrix/clip state of an SkPicture into |
22 // a series of save/restore blocks of consistent matrix clip state, e.g.: | 21 // a series of save/restore blocks of consistent matrix clip state, e.g.: |
23 // | 22 // |
24 // save | 23 // save |
25 // clip(s) | 24 // clip(s) |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 }; | 107 }; |
109 | 108 |
110 class ClipInfo : public SkNoncopyable { | 109 class ClipInfo : public SkNoncopyable { |
111 public: | 110 public: |
112 ClipInfo() {} | 111 ClipInfo() {} |
113 | 112 |
114 bool clipRect(const SkRect& rect, | 113 bool clipRect(const SkRect& rect, |
115 SkRegion::Op op, | 114 SkRegion::Op op, |
116 bool doAA, | 115 bool doAA, |
117 int matrixID) { | 116 int matrixID) { |
118 ClipOp& newClip = fClips.push_back(); | 117 ClipOp* newClip = fClips.append(); |
119 newClip.fClipType = kRect_ClipType; | 118 newClip->fClipType = kRect_ClipType; |
120 newClip.fGeom.fRRect.setRect(rect); // storing the clipRect in
the RRect | 119 newClip->fGeom.fRRect.setRect(rect); // storing the clipRect i
n the RRect |
121 newClip.fOp = op; | 120 newClip->fOp = op; |
122 newClip.fDoAA = doAA; | 121 newClip->fDoAA = doAA; |
123 newClip.fMatrixID = matrixID; | 122 newClip->fMatrixID = matrixID; |
124 newClip.fOffset = kInvalidJumpOffset; | 123 newClip->fOffset = kInvalidJumpOffset; |
125 return false; | 124 return false; |
126 } | 125 } |
127 | 126 |
128 bool clipRRect(const SkRRect& rrect, | 127 bool clipRRect(const SkRRect& rrect, |
129 SkRegion::Op op, | 128 SkRegion::Op op, |
130 bool doAA, | 129 bool doAA, |
131 int matrixID) { | 130 int matrixID) { |
132 ClipOp& newClip = fClips.push_back(); | 131 ClipOp* newClip = fClips.append(); |
133 newClip.fClipType = kRRect_ClipType; | 132 newClip->fClipType = kRRect_ClipType; |
134 newClip.fGeom.fRRect = rrect; | 133 newClip->fGeom.fRRect = rrect; |
135 newClip.fOp = op; | 134 newClip->fOp = op; |
136 newClip.fDoAA = doAA; | 135 newClip->fDoAA = doAA; |
137 newClip.fMatrixID = matrixID; | 136 newClip->fMatrixID = matrixID; |
138 newClip.fOffset = kInvalidJumpOffset; | 137 newClip->fOffset = kInvalidJumpOffset; |
139 return false; | 138 return false; |
140 } | 139 } |
141 | 140 |
142 bool clipPath(SkPictureRecord* picRecord, | 141 bool clipPath(SkPictureRecord* picRecord, |
143 const SkPath& path, | 142 const SkPath& path, |
144 SkRegion::Op op, | 143 SkRegion::Op op, |
145 bool doAA, | 144 bool doAA, |
146 int matrixID); | 145 int matrixID); |
147 bool clipRegion(SkPictureRecord* picRecord, | 146 bool clipRegion(SkPictureRecord* picRecord, |
148 const SkRegion& region, | 147 int regionID, |
149 SkRegion::Op op, | 148 SkRegion::Op op, |
150 int matrixID); | 149 int matrixID); |
151 void writeClip(int* curMatID, | 150 void writeClip(int* curMatID, |
152 SkMatrixClipStateMgr* mgr, | 151 SkMatrixClipStateMgr* mgr, |
153 bool* overrideFirstOp); | 152 bool* overrideFirstOp); |
154 void fillInSkips(SkWriter32* writer, int32_t restoreOffset); | 153 void fillInSkips(SkWriter32* writer, int32_t restoreOffset); |
155 | 154 |
156 #ifdef SK_DEBUG | 155 #ifdef SK_DEBUG |
157 void checkOffsetNotEqual(int32_t offset) { | 156 void checkOffsetNotEqual(int32_t offset) { |
158 for (int i = 0; i < fClips.count(); ++i) { | 157 for (int i = 0; i < fClips.count(); ++i) { |
159 ClipOp& curClip = fClips[i]; | 158 ClipOp& curClip = fClips[i]; |
160 SkASSERT(offset != curClip.fOffset); | 159 SkASSERT(offset != curClip.fOffset); |
161 } | 160 } |
162 } | 161 } |
163 #endif | 162 #endif |
164 private: | 163 private: |
165 enum ClipType { | 164 enum ClipType { |
166 kRect_ClipType, | 165 kRect_ClipType, |
167 kRRect_ClipType, | 166 kRRect_ClipType, |
168 kPath_ClipType, | 167 kPath_ClipType, |
169 kRegion_ClipType | 168 kRegion_ClipType |
170 }; | 169 }; |
171 | 170 |
172 static const int kInvalidJumpOffset = -1; | 171 static const int kInvalidJumpOffset = -1; |
173 | 172 |
174 class ClipOp { | 173 class ClipOp { |
175 public: | 174 public: |
176 ClipOp() {} | |
177 ~ClipOp() { | |
178 if (kRegion_ClipType == fClipType) { | |
179 SkDELETE(fGeom.fRegion); | |
180 } | |
181 } | |
182 | |
183 ClipType fClipType; | 175 ClipType fClipType; |
184 | 176 |
185 union { | 177 union { |
186 SkRRect fRRect; // also stores clipRect | 178 SkRRect fRRect; // also stores clipRect |
187 int fPathID; | 179 int fPathID; |
188 // TODO: add internal dictionary of regions | 180 int fRegionID; |
189 // This parameter forces us to have a dtor and thus use | |
190 // SkTArray rather then SkTDArray! | |
191 const SkRegion* fRegion; | |
192 } fGeom; | 181 } fGeom; |
193 | 182 |
194 bool fDoAA; | 183 bool fDoAA; |
195 SkRegion::Op fOp; | 184 SkRegion::Op fOp; |
196 | 185 |
197 // The CTM in effect when this clip call was issued | 186 // The CTM in effect when this clip call was issued |
198 int fMatrixID; | 187 int fMatrixID; |
199 | 188 |
200 // The offset of this clipOp's "jump-to-offset" location in the
skp. | 189 // The offset of this clipOp's "jump-to-offset" location in the
skp. |
201 // -1 means the offset hasn't been written. | 190 // -1 means the offset hasn't been written. |
202 int32_t fOffset; | 191 int32_t fOffset; |
203 }; | 192 }; |
204 | 193 |
205 SkTArray<ClipOp> fClips; | 194 SkTDArray<ClipOp> fClips; |
206 | 195 |
207 typedef SkNoncopyable INHERITED; | 196 typedef SkNoncopyable INHERITED; |
208 }; | 197 }; |
209 | 198 |
210 MatrixClipState(MatrixClipState* prev, int flags) | 199 MatrixClipState(MatrixClipState* prev, int flags) |
211 #ifdef SK_DEBUG | 200 #ifdef SK_DEBUG |
212 : fPrev(prev) | 201 : fPrev(prev) |
213 #endif | 202 #endif |
214 { | 203 { |
215 if (NULL == prev) { | 204 if (NULL == prev) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 int32_t fMCStateID; | 258 int32_t fMCStateID; |
270 }; | 259 }; |
271 | 260 |
272 enum CallType { | 261 enum CallType { |
273 kMatrix_CallType, | 262 kMatrix_CallType, |
274 kClip_CallType, | 263 kClip_CallType, |
275 kOther_CallType | 264 kOther_CallType |
276 }; | 265 }; |
277 | 266 |
278 SkMatrixClipStateMgr(); | 267 SkMatrixClipStateMgr(); |
| 268 ~SkMatrixClipStateMgr(); |
279 | 269 |
280 void init(SkPictureRecord* picRecord) { | 270 void init(SkPictureRecord* picRecord) { |
281 // Note: we're not taking a ref here. It is expected that the SkMatrixCl
ipStateMgr | 271 // Note: we're not taking a ref here. It is expected that the SkMatrixCl
ipStateMgr |
282 // is owned by the SkPictureRecord object | 272 // is owned by the SkPictureRecord object |
283 fPicRecord = picRecord; | 273 fPicRecord = picRecord; |
284 } | 274 } |
285 | 275 |
286 SkPictureRecord* getPicRecord() { return fPicRecord; } | 276 SkPictureRecord* getPicRecord() { return fPicRecord; } |
287 | 277 |
288 // TODO: need to override canvas' getSaveCount. Right now we pass the | 278 // TODO: need to override canvas' getSaveCount. Right now we pass the |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 } | 333 } |
344 | 334 |
345 bool clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { | 335 bool clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { |
346 this->call(SkMatrixClipStateMgr::kClip_CallType); | 336 this->call(SkMatrixClipStateMgr::kClip_CallType); |
347 return fCurMCState->fClipInfo->clipPath(fPicRecord, path, op, doAA, | 337 return fCurMCState->fClipInfo->clipPath(fPicRecord, path, op, doAA, |
348 fCurMCState->fMatrixInfo->getID(
this)); | 338 fCurMCState->fMatrixInfo->getID(
this)); |
349 } | 339 } |
350 | 340 |
351 bool clipRegion(const SkRegion& region, SkRegion::Op op) { | 341 bool clipRegion(const SkRegion& region, SkRegion::Op op) { |
352 this->call(SkMatrixClipStateMgr::kClip_CallType); | 342 this->call(SkMatrixClipStateMgr::kClip_CallType); |
353 return fCurMCState->fClipInfo->clipRegion(fPicRecord, region, op, | 343 int regionID = this->addRegionToDict(region); |
| 344 return fCurMCState->fClipInfo->clipRegion(fPicRecord, regionID, op, |
354 fCurMCState->fMatrixInfo->getI
D(this)); | 345 fCurMCState->fMatrixInfo->getI
D(this)); |
355 } | 346 } |
356 | 347 |
357 bool call(CallType callType); | 348 bool call(CallType callType); |
358 | 349 |
359 void fillInSkips(SkWriter32* writer, int32_t restoreOffset) { | 350 void fillInSkips(SkWriter32* writer, int32_t restoreOffset) { |
360 // Since we write out the entire clip stack at each block start we | 351 // Since we write out the entire clip stack at each block start we |
361 // need to update the skips for the entire stack each time too. | 352 // need to update the skips for the entire stack each time too. |
362 SkDeque::F2BIter iter(fMatrixClipStack); | 353 SkDeque::F2BIter iter(fMatrixClipStack); |
363 | 354 |
(...skipping 13 matching lines...) Expand all Loading... |
377 SkDeque fMatrixClipStack; | 368 SkDeque fMatrixClipStack; |
378 MatrixClipState* fCurMCState; | 369 MatrixClipState* fCurMCState; |
379 | 370 |
380 // This dictionary doesn't actually de-duplicate the matrices (except for th
e | 371 // This dictionary doesn't actually de-duplicate the matrices (except for th
e |
381 // identity matrix). It merely stores the matrices and allows them to be loo
ked | 372 // identity matrix). It merely stores the matrices and allows them to be loo
ked |
382 // up by ID later. The de-duplication mainly falls upon the matrix/clip stac
k | 373 // up by ID later. The de-duplication mainly falls upon the matrix/clip stac
k |
383 // which stores the ID so a revisited clip/matrix (via popping the stack) wi
ll | 374 // which stores the ID so a revisited clip/matrix (via popping the stack) wi
ll |
384 // use the same ID. | 375 // use the same ID. |
385 SkTDArray<SkMatrix> fMatrixDict; | 376 SkTDArray<SkMatrix> fMatrixDict; |
386 | 377 |
| 378 SkTDArray<SkRegion*> fRegionDict; |
| 379 |
387 // The MCStateID of the state currently in effect in the byte stream. 0 if n
one. | 380 // The MCStateID of the state currently in effect in the byte stream. 0 if n
one. |
388 int32_t fCurOpenStateID; | 381 int32_t fCurOpenStateID; |
389 | 382 |
390 SkDEBUGCODE(void validate();) | 383 SkDEBUGCODE(void validate();) |
391 | 384 |
392 void writeDeltaMat(int currentMatID, int desiredMatID); | 385 void writeDeltaMat(int currentMatID, int desiredMatID); |
393 static int32_t NewMCStateID(); | 386 static int32_t NewMCStateID(); |
394 | 387 |
| 388 int addRegionToDict(const SkRegion& region); |
| 389 const SkRegion* lookupRegion(int index) { |
| 390 SkASSERT(index >= 0 && index < fRegionDict.count()); |
| 391 return fRegionDict[index]; |
| 392 } |
| 393 |
395 // TODO: add stats to check if the dictionary really does | 394 // TODO: add stats to check if the dictionary really does |
396 // reduce the size of the SkPicture. | 395 // reduce the size of the SkPicture. |
397 int addMatToDict(const SkMatrix& mat); | 396 int addMatToDict(const SkMatrix& mat); |
398 const SkMatrix& lookupMat(int index) { | 397 const SkMatrix& lookupMat(int index) { |
399 SkASSERT(index >= 0 && index < fMatrixDict.count()); | 398 SkASSERT(index >= 0 && index < fMatrixDict.count()); |
400 return fMatrixDict[index]; | 399 return fMatrixDict[index]; |
401 } | 400 } |
402 }; | 401 }; |
403 | 402 |
404 #endif | 403 #endif |
OLD | NEW |