OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #ifndef SkPictureRecord_DEFINED | 8 #ifndef SkPictureRecord_DEFINED |
9 #define SkPictureRecord_DEFINED | 9 #define SkPictureRecord_DEFINED |
10 | 10 |
11 #include "SkCanvas.h" | 11 #include "SkCanvas.h" |
12 #include "SkFlattenable.h" | 12 #include "SkFlattenable.h" |
13 #include "SkPathHeap.h" | 13 #include "SkPathHeap.h" |
14 #include "SkPicture.h" | 14 #include "SkPicture.h" |
15 #include "SkPictureFlat.h" | 15 #include "SkPictureFlat.h" |
16 #include "SkTemplates.h" | 16 #include "SkTemplates.h" |
17 #include "SkWriter32.h" | 17 #include "SkWriter32.h" |
18 | 18 |
| 19 #define COLLAPSE_MATRIX_CLIP_STATE 1 |
| 20 |
| 21 #ifdef COLLAPSE_MATRIX_CLIP_STATE |
| 22 #include "SkTypes.h" |
| 23 |
| 24 class MatrixClipState { |
| 25 public: |
| 26 class MatrixInfo { |
| 27 public: |
| 28 SkMatrix fMatrix; |
| 29 // TODO: add an internal dictionary and an ID here |
| 30 }; |
| 31 |
| 32 class ClipInfo : public SkNoncopyable { |
| 33 public: |
| 34 ClipInfo() {} |
| 35 |
| 36 bool clipRect(const SkRect& rect, SkRegion::Op op, bool doAA, const SkMa
trix& matrix) { |
| 37 ClipOp* newClip = fClips.append(); |
| 38 newClip->fClipType = kRect_ClipType; |
| 39 newClip->fGeom.fRRect.setRect(rect); // store the clipRect in the
RRect |
| 40 newClip->fOp = op; |
| 41 newClip->fDoAA = doAA; |
| 42 newClip->fMatrix = matrix; |
| 43 newClip->fOffset = kInvalidJumpOffset; |
| 44 return false; |
| 45 } |
| 46 |
| 47 bool clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA, const S
kMatrix& matrix) { |
| 48 ClipOp* newClip = fClips.append(); |
| 49 newClip->fClipType = kRRect_ClipType; |
| 50 newClip->fGeom.fRRect = rrect; |
| 51 newClip->fOp = op; |
| 52 newClip->fDoAA = doAA; |
| 53 newClip->fMatrix = matrix; |
| 54 newClip->fOffset = kInvalidJumpOffset; |
| 55 return false; |
| 56 } |
| 57 |
| 58 bool clipPath(SkPictureRecord* picRecord, |
| 59 const SkPath& path, |
| 60 SkRegion::Op op, |
| 61 bool doAA, |
| 62 const SkMatrix& matrix); |
| 63 bool clipRegion(SkPictureRecord* picRecord, |
| 64 const SkRegion& region, |
| 65 SkRegion::Op op, |
| 66 const SkMatrix& matrix); |
| 67 void writeClip(SkMatrix* curMat, SkPictureRecord* picRecord, |
| 68 bool* overrideFirstOp); |
| 69 void fillInSkips(SkWriter32* writer, int32_t restoreOffset); |
| 70 |
| 71 private: |
| 72 enum ClipType { |
| 73 kRect_ClipType, |
| 74 kRRect_ClipType, |
| 75 kPath_ClipType, |
| 76 kRegion_ClipType |
| 77 }; |
| 78 |
| 79 static const int kInvalidJumpOffset = -1; |
| 80 |
| 81 struct ClipOp { |
| 82 ClipType fClipType; |
| 83 |
| 84 union { |
| 85 SkRRect fRRect; // also stores clipRect |
| 86 int fPathID; |
| 87 // TODO: add internal dictionary of regions |
| 88 // Arrg - need to free this in dtor!!! |
| 89 const SkRegion* fRegion; |
| 90 } fGeom; |
| 91 |
| 92 bool fDoAA; |
| 93 SkRegion::Op fOp; |
| 94 |
| 95 // This used to be and int (when matrices were in a dictionary) |
| 96 // now it is a full matrix. |
| 97 // The CTM in effect when this clip call was issued |
| 98 SkMatrix fMatrix; |
| 99 |
| 100 // The offset of this clipOp's "jump-to-offset" variable in the skp. |
| 101 // -1 means the offset hasn't been written. |
| 102 int32_t fOffset; |
| 103 }; |
| 104 |
| 105 SkTDArray<ClipOp> fClips; |
| 106 |
| 107 typedef SkNoncopyable INHERITED; |
| 108 }; |
| 109 |
| 110 MatrixClipState(MatrixClipState *prev, int flags) { |
| 111 if (NULL == prev) { |
| 112 fLayerID = 0; |
| 113 |
| 114 fMatrixInfoStorage.fMatrix.reset(); |
| 115 fMatrixInfo = &fMatrixInfoStorage; |
| 116 fClipInfo = &fClipInfoStorage; |
| 117 |
| 118 fIsCurrent = true; |
| 119 } |
| 120 else { |
| 121 fLayerID = prev->fLayerID; |
| 122 |
| 123 if (flags & SkCanvas::kMatrix_SaveFlag) { |
| 124 fMatrixInfoStorage = *prev->fMatrixInfo; |
| 125 fMatrixInfo = &fMatrixInfoStorage; |
| 126 } else { |
| 127 fMatrixInfo = prev->fMatrixInfo; |
| 128 } |
| 129 |
| 130 if (flags & SkCanvas::kClip_SaveFlag) { |
| 131 // We don't copy the ClipOps of the previous clip states |
| 132 fClipInfo = &fClipInfoStorage; |
| 133 } else { |
| 134 fClipInfo = prev->fClipInfo; |
| 135 } |
| 136 |
| 137 fIsCurrent = prev->fIsCurrent; |
| 138 } |
| 139 |
| 140 fWroteSave = false; |
| 141 fIsSaveLayer = false; |
| 142 } |
| 143 |
| 144 MatrixInfo* fMatrixInfo; |
| 145 MatrixInfo fMatrixInfoStorage; |
| 146 |
| 147 ClipInfo* fClipInfo; |
| 148 ClipInfo fClipInfoStorage; |
| 149 |
| 150 int fLayerID; |
| 151 // Does this MC state represent a saveLayer call? |
| 152 bool fIsSaveLayer; |
| 153 // Is this the current MC state in the picture command stream? |
| 154 bool fIsCurrent; |
| 155 // Is there an unbalanced 'save' for this MC state already in the command st
ream? |
| 156 bool fWroteSave; |
| 157 }; |
| 158 |
| 159 |
| 160 class MatrixClipStateMgr { |
| 161 public: |
| 162 enum CallType { |
| 163 kMatrix_CallType, |
| 164 kClip_CallType, |
| 165 kOther_CallType |
| 166 }; |
| 167 |
| 168 MatrixClipStateMgr(); |
| 169 |
| 170 void init(SkPictureRecord* picRecord) { |
| 171 fPicRecord = picRecord; |
| 172 } |
| 173 |
| 174 // TODO: need to override canvas' getSaveCount |
| 175 int getSaveCount() const { return fMatrixClipStack.count(); } |
| 176 |
| 177 int save(SkCanvas::SaveFlags flags) { |
| 178 MatrixClipState* newTop = (MatrixClipState*)fMatrixClipStack.push_back()
; |
| 179 new (newTop) MatrixClipState(fCurMCState, flags); // balanced in rest
ore() |
| 180 fCurMCState = newTop; |
| 181 return fMatrixClipStack.count(); |
| 182 } |
| 183 |
| 184 int saveLayer(const SkRect* bounds, const SkPaint* paint, |
| 185 SkCanvas::SaveFlags flags) { |
| 186 int result = this->save(flags); |
| 187 ++fCurMCState->fLayerID; |
| 188 fCurMCState->fIsSaveLayer = true; |
| 189 return result; |
| 190 } |
| 191 |
| 192 bool isDrawingToLayer() const { |
| 193 return fCurMCState->fLayerID > 0; |
| 194 } |
| 195 |
| 196 void restore(); |
| 197 |
| 198 bool translate(SkScalar dx, SkScalar dy) { |
| 199 this->call(kMatrix_CallType); |
| 200 bool result = fCurMCState->fMatrixInfo->fMatrix.preTranslate(dx, dy); |
| 201 // fCurMCState->fMatrixInfo->fID = -1; |
| 202 fCurMCState->fIsCurrent = false; |
| 203 return result; |
| 204 } |
| 205 |
| 206 bool scale(SkScalar sx, SkScalar sy) { |
| 207 this->call(kMatrix_CallType); |
| 208 bool result = fCurMCState->fMatrixInfo->fMatrix.preScale(sx, sy); |
| 209 // fCurMCState->fMatrixInfo->fID = -1; |
| 210 fCurMCState->fIsCurrent = false; |
| 211 return result; |
| 212 } |
| 213 |
| 214 bool rotate(SkScalar degrees) { |
| 215 this->call(kMatrix_CallType); |
| 216 bool result = fCurMCState->fMatrixInfo->fMatrix.preRotate(degrees); |
| 217 // fCurMCState->fMatrixInfo->fID = -1; |
| 218 fCurMCState->fIsCurrent = false; |
| 219 return result; |
| 220 } |
| 221 |
| 222 bool skew(SkScalar sx, SkScalar sy) { |
| 223 this->call(kMatrix_CallType); |
| 224 bool result = fCurMCState->fMatrixInfo->fMatrix.preSkew(sx, sy); |
| 225 // fCurMCState->fMatrixInfo->fID = -1; |
| 226 fCurMCState->fIsCurrent = false; |
| 227 return result; |
| 228 } |
| 229 |
| 230 bool concat(const SkMatrix& matrix) { |
| 231 this->call(kMatrix_CallType); |
| 232 bool result = fCurMCState->fMatrixInfo->fMatrix.preConcat(matrix); |
| 233 // fCurMCState->fMatrixInfo->fID = -1; |
| 234 fCurMCState->fIsCurrent = false; |
| 235 return result; |
| 236 } |
| 237 |
| 238 void setMatrix(const SkMatrix& matrix) { |
| 239 this->call(kMatrix_CallType); |
| 240 fCurMCState->fMatrixInfo->fMatrix = matrix; |
| 241 // fCurMCState->fMatrixInfo->fID = -1; |
| 242 fCurMCState->fIsCurrent = false; |
| 243 } |
| 244 |
| 245 bool clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { |
| 246 this->call(MatrixClipStateMgr::kClip_CallType); |
| 247 |
| 248 fCurMCState->fIsCurrent = false; |
| 249 return fCurMCState->fClipInfo->clipRect(rect, op, doAA, |
| 250 fCurMCState->fMatrixInfo->fMatri
x); |
| 251 } |
| 252 |
| 253 bool clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { |
| 254 this->call(MatrixClipStateMgr::kClip_CallType); |
| 255 |
| 256 fCurMCState->fIsCurrent = false; |
| 257 return fCurMCState->fClipInfo->clipRRect(rrect, op, doAA, |
| 258 fCurMCState->fMatrixInfo->fMatr
ix); |
| 259 } |
| 260 |
| 261 bool clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { |
| 262 this->call(MatrixClipStateMgr::kClip_CallType); |
| 263 |
| 264 fCurMCState->fIsCurrent = false; |
| 265 bool result = fCurMCState->fClipInfo->clipPath(fPicRecord, path, op, doA
A, |
| 266 fCurMCState->fMatrixInfo-
>fMatrix); |
| 267 return result; |
| 268 } |
| 269 |
| 270 bool clipRegion(const SkRegion& region, SkRegion::Op op) { |
| 271 this->call(MatrixClipStateMgr::kClip_CallType); |
| 272 |
| 273 fCurMCState->fIsCurrent = false; |
| 274 bool result = fCurMCState->fClipInfo->clipRegion(fPicRecord, region, op, |
| 275 fCurMCState->fMatrixInf
o->fMatrix); |
| 276 return result; |
| 277 } |
| 278 |
| 279 void call(CallType callType); |
| 280 |
| 281 void fillInSkips(SkWriter32* writer, int32_t restoreOffset) { |
| 282 fCurMCState->fClipInfo->fillInSkips(writer, restoreOffset); |
| 283 } |
| 284 |
| 285 void finish1() { |
| 286 #if 0 |
| 287 if (fCurMCState->fWroteSave) { |
| 288 fCurMCState->fWroteSave = false; |
| 289 fPicRecord->restoreImpl(); |
| 290 } |
| 291 #endif |
| 292 } |
| 293 |
| 294 protected: |
| 295 SkPictureRecord* fPicRecord; |
| 296 |
| 297 uint32_t fMatrixClipStackStorage[43]; // sized to fit 2 clip states |
| 298 SkDeque fMatrixClipStack; |
| 299 MatrixClipState* fCurMCState; |
| 300 }; |
| 301 #endif |
| 302 |
| 303 |
19 class SkPictureStateTree; | 304 class SkPictureStateTree; |
20 class SkBBoxHierarchy; | 305 class SkBBoxHierarchy; |
21 | 306 |
22 // These macros help with packing and unpacking a single byte value and | 307 // These macros help with packing and unpacking a single byte value and |
23 // a 3 byte value into/out of a uint32_t | 308 // a 3 byte value into/out of a uint32_t |
24 #define MASK_24 0x00FFFFFF | 309 #define MASK_24 0x00FFFFFF |
25 #define UNPACK_8_24(combined, small, large) \ | 310 #define UNPACK_8_24(combined, small, large) \ |
26 small = (combined >> 24) & 0xFF; \ | 311 small = (combined >> 24) & 0xFF; \ |
27 large = combined & MASK_24; | 312 large = combined & MASK_24; |
28 #define PACK_8_24(small, large) ((small << 24) | large) | 313 #define PACK_8_24(small, large) ((small << 24) | large) |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 | 386 |
102 const SkWriter32& writeStream() const { | 387 const SkWriter32& writeStream() const { |
103 return fWriter; | 388 return fWriter; |
104 } | 389 } |
105 | 390 |
106 void beginRecording(); | 391 void beginRecording(); |
107 void endRecording(); | 392 void endRecording(); |
108 | 393 |
109 private: | 394 private: |
110 void handleOptimization(int opt); | 395 void handleOptimization(int opt); |
111 void recordRestoreOffsetPlaceholder(SkRegion::Op); | 396 int recordRestoreOffsetPlaceholder(SkRegion::Op); |
112 void fillRestoreOffsetPlaceholdersForCurrentStackLevel( | 397 void fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffse
t); |
113 uint32_t restoreOffset); | |
114 | 398 |
| 399 #ifndef COLLAPSE_MATRIX_CLIP_STATE |
115 SkTDArray<int32_t> fRestoreOffsetStack; | 400 SkTDArray<int32_t> fRestoreOffsetStack; |
116 int fFirstSavedLayerIndex; | 401 int fFirstSavedLayerIndex; |
117 enum { | 402 enum { |
118 kNoSavedLayerIndex = -1 | 403 kNoSavedLayerIndex = -1 |
119 }; | 404 }; |
| 405 #endif |
120 | 406 |
121 /* | 407 /* |
122 * Write the 'drawType' operation and chunk size to the skp. 'size' | 408 * Write the 'drawType' operation and chunk size to the skp. 'size' |
123 * can potentially be increased if the chunk size needs its own storage | 409 * can potentially be increased if the chunk size needs its own storage |
124 * location (i.e., it overflows 24 bits). | 410 * location (i.e., it overflows 24 bits). |
125 * Returns the start offset of the chunk. This is the location at which | 411 * Returns the start offset of the chunk. This is the location at which |
126 * the opcode & size are stored. | 412 * the opcode & size are stored. |
127 * TODO: since we are handing the size into here we could call reserve | 413 * TODO: since we are handing the size into here we could call reserve |
128 * and then return a pointer to the memory storage. This could decrease | 414 * and then return a pointer to the memory storage. This could decrease |
129 * allocation overhead but could lead to more wasted space (the tail | 415 * allocation overhead but could lead to more wasted space (the tail |
(...skipping 24 matching lines...) Expand all Loading... |
154 } | 440 } |
155 | 441 |
156 void addInt(int value) { | 442 void addInt(int value) { |
157 fWriter.writeInt(value); | 443 fWriter.writeInt(value); |
158 } | 444 } |
159 void addScalar(SkScalar scalar) { | 445 void addScalar(SkScalar scalar) { |
160 fWriter.writeScalar(scalar); | 446 fWriter.writeScalar(scalar); |
161 } | 447 } |
162 | 448 |
163 void addBitmap(const SkBitmap& bitmap); | 449 void addBitmap(const SkBitmap& bitmap); |
| 450 int addMatrixToHeap(const SkMatrix& matrix); |
164 void addMatrix(const SkMatrix& matrix); | 451 void addMatrix(const SkMatrix& matrix); |
165 const SkFlatData* addPaint(const SkPaint& paint) { return this->addPaintPtr(
&paint); } | 452 const SkFlatData* addPaint(const SkPaint& paint) { return this->addPaintPtr(
&paint); } |
166 const SkFlatData* addPaintPtr(const SkPaint* paint); | 453 const SkFlatData* addPaintPtr(const SkPaint* paint); |
167 void addFlatPaint(const SkFlatData* flatPaint); | 454 void addFlatPaint(const SkFlatData* flatPaint); |
| 455 int addPathToHeap(const SkPath& path); |
168 void addPath(const SkPath& path); | 456 void addPath(const SkPath& path); |
169 void addPicture(SkPicture& picture); | 457 void addPicture(SkPicture& picture); |
170 void addPoint(const SkPoint& point); | 458 void addPoint(const SkPoint& point); |
171 void addPoints(const SkPoint pts[], int count); | 459 void addPoints(const SkPoint pts[], int count); |
172 void addRect(const SkRect& rect); | 460 void addRect(const SkRect& rect); |
173 void addRectPtr(const SkRect* rect); | 461 void addRectPtr(const SkRect* rect); |
174 void addIRect(const SkIRect& rect); | 462 void addIRect(const SkIRect& rect); |
175 void addIRectPtr(const SkIRect* rect); | 463 void addIRectPtr(const SkIRect* rect); |
176 void addRRect(const SkRRect&); | 464 void addRRect(const SkRRect&); |
| 465 int addRegionToHeap(const SkRegion& region); |
177 void addRegion(const SkRegion& region); | 466 void addRegion(const SkRegion& region); |
178 void addText(const void* text, size_t byteLength); | 467 void addText(const void* text, size_t byteLength); |
179 | 468 |
180 int find(const SkBitmap& bitmap); | 469 int find(const SkBitmap& bitmap); |
181 | 470 |
182 #ifdef SK_DEBUG_DUMP | 471 #ifdef SK_DEBUG_DUMP |
183 public: | 472 public: |
184 void dumpMatrices(); | 473 void dumpMatrices(); |
185 void dumpPaints(); | 474 void dumpPaints(); |
186 #endif | 475 #endif |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 // Will return a cached version when possible. | 519 // Will return a cached version when possible. |
231 const SkFlatData* getFlatPaintData(const SkPaint& paint); | 520 const SkFlatData* getFlatPaintData(const SkPaint& paint); |
232 /** | 521 /** |
233 * SkBBoxRecord::drawPosTextH gets a flat paint and uses it, | 522 * SkBBoxRecord::drawPosTextH gets a flat paint and uses it, |
234 * then it calls this, using the extra parameter, to avoid duplication. | 523 * then it calls this, using the extra parameter, to avoid duplication. |
235 */ | 524 */ |
236 void drawPosTextHImpl(const void* text, size_t byteLength, | 525 void drawPosTextHImpl(const void* text, size_t byteLength, |
237 const SkScalar xpos[], SkScalar constY, | 526 const SkScalar xpos[], SkScalar constY, |
238 const SkPaint& paint, const SkFlatData* flatPaintData)
; | 527 const SkPaint& paint, const SkFlatData* flatPaintData)
; |
239 | 528 |
| 529 void concatImpl(const SkMatrix& matrix); |
| 530 void setMatrixImpl(const SkMatrix& matrix); |
| 531 int clipRectImpl(const SkRect& rect, SkRegion::Op op, bool doAA); |
| 532 int clipRRectImpl(const SkRRect& rrect, SkRegion::Op op, bool doAA); |
| 533 int clipPathImpl(int pathID, SkRegion::Op op, bool doAA); |
| 534 int clipRegionImpl(const SkRegion& region, SkRegion::Op op); |
| 535 void saveImpl(SaveFlags flags); |
| 536 void restoreImpl(); |
| 537 |
240 // These are set to NULL in our constructor, but may be changed by | 538 // These are set to NULL in our constructor, but may be changed by |
241 // subclasses, in which case they will be SkSafeUnref'd in our destructor. | 539 // subclasses, in which case they will be SkSafeUnref'd in our destructor. |
242 SkBBoxHierarchy* fBoundingHierarchy; | 540 SkBBoxHierarchy* fBoundingHierarchy; |
243 SkPictureStateTree* fStateTree; | 541 SkPictureStateTree* fStateTree; |
244 | 542 |
245 // Allocated in the constructor and managed by this class. | 543 // Allocated in the constructor and managed by this class. |
246 SkBitmapHeap* fBitmapHeap; | 544 SkBitmapHeap* fBitmapHeap; |
247 | 545 |
248 private: | 546 private: |
| 547 #ifdef COLLAPSE_MATRIX_CLIP_STATE |
| 548 friend class MatrixClipState; // for access to *Impl methods |
| 549 friend class MatrixClipStateMgr; // for access to *Impl methods |
| 550 #endif |
| 551 |
249 SkChunkFlatController fFlattenableHeap; | 552 SkChunkFlatController fFlattenableHeap; |
250 | 553 |
251 SkPaintDictionary fPaints; | 554 SkPaintDictionary fPaints; |
252 | 555 |
253 SkPathHeap* fPathHeap; // reference counted | 556 SkPathHeap* fPathHeap; // reference counted |
254 SkWriter32 fWriter; | 557 SkWriter32 fWriter; |
255 | 558 |
256 // we ref each item in these arrays | 559 // we ref each item in these arrays |
257 SkTDArray<SkPicture*> fPictureRefs; | 560 SkTDArray<SkPicture*> fPictureRefs; |
258 | 561 |
259 uint32_t fRecordFlags; | 562 uint32_t fRecordFlags; |
260 int fInitialSaveCount; | 563 int fInitialSaveCount; |
261 | 564 |
262 friend class SkPicturePlayback; | 565 friend class SkPicturePlayback; |
263 friend class SkPictureTester; // for unit testing | 566 friend class SkPictureTester; // for unit testing |
264 | 567 |
| 568 #ifdef COLLAPSE_MATRIX_CLIP_STATE |
| 569 MatrixClipStateMgr fMCMgr; |
| 570 #endif |
| 571 |
265 typedef SkCanvas INHERITED; | 572 typedef SkCanvas INHERITED; |
266 }; | 573 }; |
267 | 574 |
268 #endif | 575 #endif |
OLD | NEW |