1 /*
2 * Copyright 2011 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
8 #include "src/core/SkPictureRecord.h"
9
10 #include "include/core/SkRRect.h"
11 #include "include/core/SkRSXform.h"
12 #include "include/core/SkTextBlob.h"
13 #include "include/private/SkTo.h"
14 #include "src/core/SkCanvasPriv.h"
15 #include "src/core/SkClipOpPriv.h"
16 #include "src/core/SkDrawShadowInfo.h"
17 #include "src/core/SkMatrixPriv.h"
18 #include "src/core/SkTSearch.h"
19 #include "src/image/SkImage_Base.h"
20 #include "src/utils/SkPatchUtils.h"
21
22 #define HEAP_BLOCK_SIZE 4096
23
24 enum {
25 // just need a value that save or getSaveCount would never return
26 kNoInitialSave = -1,
27 };
28
29 // A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
30 static int const kUInt32Size = 4;
31
SkPictureRecord(const SkIRect & dimensions,uint32_t flags)32 SkPictureRecord::SkPictureRecord(const SkIRect& dimensions, uint32_t flags)
33 : INHERITED(dimensions)
34 , fRecordFlags(flags)
35 , fInitialSaveCount(kNoInitialSave) {
36 }
37
SkPictureRecord(const SkISize & dimensions,uint32_t flags)38 SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
39 : SkPictureRecord(SkIRect::MakeSize(dimensions), flags) {}
40
41 ///////////////////////////////////////////////////////////////////////////////
42
onFlush()43 void SkPictureRecord::onFlush() {
44 size_t size = sizeof(kUInt32Size);
45 size_t initialOffset = this->addDraw(FLUSH, &size);
46 this->validate(initialOffset, size);
47 }
48
willSave()49 void SkPictureRecord::willSave() {
50 // record the offset to us, making it non-positive to distinguish a save
51 // from a clip entry.
52 fRestoreOffsetStack.push_back(-(int32_t)fWriter.bytesWritten());
53 this->recordSave();
54
55 this->INHERITED::willSave();
56 }
57
recordSave()58 void SkPictureRecord::recordSave() {
59 // op only
60 size_t size = sizeof(kUInt32Size);
61 size_t initialOffset = this->addDraw(SAVE, &size);
62
63 this->validate(initialOffset, size);
64 }
65
getSaveLayerStrategy(const SaveLayerRec & rec)66 SkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) {
67 // record the offset to us, making it non-positive to distinguish a save
68 // from a clip entry.
69 fRestoreOffsetStack.push_back(-(int32_t)fWriter.bytesWritten());
70 this->recordSaveLayer(rec);
71
72 (void)this->INHERITED::getSaveLayerStrategy(rec);
73 /* No need for a (potentially very big) layer which we don't actually need
74 at this time (and may not be able to afford since during record our
75 clip starts out the size of the picture, which is often much larger
76 than the size of the actual device we'll use during playback).
77 */
78 return kNoLayer_SaveLayerStrategy;
79 }
80
onDoSaveBehind(const SkRect * subset)81 bool SkPictureRecord::onDoSaveBehind(const SkRect* subset) {
82 fRestoreOffsetStack.push_back(-(int32_t)fWriter.bytesWritten());
83
84 size_t size = sizeof(kUInt32Size) + sizeof(uint32_t); // op + flags
85 uint32_t flags = 0;
86 if (subset) {
87 flags |= SAVEBEHIND_HAS_SUBSET;
88 size += sizeof(*subset);
89 }
90
91 size_t initialOffset = this->addDraw(SAVE_BEHIND, &size);
92 this->addInt(flags);
93 if (subset) {
94 this->addRect(*subset);
95 }
96
97 this->validate(initialOffset, size);
98 return false;
99 }
100
recordSaveLayer(const SaveLayerRec & rec)101 void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
102 // op + flatflags
103 size_t size = 2 * kUInt32Size;
104 uint32_t flatFlags = 0;
105
106 if (rec.fBounds) {
107 flatFlags |= SAVELAYERREC_HAS_BOUNDS;
108 size += sizeof(*rec.fBounds);
109 }
110 if (rec.fPaint) {
111 flatFlags |= SAVELAYERREC_HAS_PAINT;
112 size += sizeof(uint32_t); // index
113 }
114 if (rec.fBackdrop) {
115 flatFlags |= SAVELAYERREC_HAS_BACKDROP;
116 size += sizeof(uint32_t); // (paint) index
117 }
118 if (rec.fSaveLayerFlags) {
119 flatFlags |= SAVELAYERREC_HAS_FLAGS;
120 size += sizeof(uint32_t);
121 }
122 if (rec.fClipMask) {
123 flatFlags |= SAVELAYERREC_HAS_CLIPMASK;
124 size += sizeof(uint32_t); // clip image index
125 }
126 if (rec.fClipMatrix) {
127 flatFlags |= SAVELAYERREC_HAS_CLIPMATRIX;
128 size += SkMatrixPriv::WriteToMemory(*rec.fClipMatrix, nullptr);
129 }
130
131 const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
132 this->addInt(flatFlags);
133 if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
134 this->addRect(*rec.fBounds);
135 }
136 if (flatFlags & SAVELAYERREC_HAS_PAINT) {
137 this->addPaintPtr(rec.fPaint);
138 }
139 if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
140 // overkill, but we didn't already track single flattenables, so using a paint for that
141 SkPaint paint;
142 paint.setImageFilter(sk_ref_sp(const_cast<SkImageFilter*>(rec.fBackdrop)));
143 this->addPaint(paint);
144 }
145 if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
146 this->addInt(rec.fSaveLayerFlags);
147 }
148 if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
149 this->addImage(rec.fClipMask);
150 }
151 if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
152 this->addMatrix(*rec.fClipMatrix);
153 }
154 this->validate(initialOffset, size);
155 }
156
157 #ifdef SK_DEBUG
158 /*
159 * Read the op code from 'offset' in 'writer' and extract the size too.
160 */
peek_op_and_size(SkWriter32 * writer,size_t offset,uint32_t * size)161 static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
162 uint32_t peek = writer->readTAt<uint32_t>(offset);
163
164 uint32_t op;
165 UNPACK_8_24(peek, op, *size);
166 if (MASK_24 == *size) {
167 // size required its own slot right after the op code
168 *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
169 }
170 return (DrawType) op;
171 }
172 #endif//SK_DEBUG
173
willRestore()174 void SkPictureRecord::willRestore() {
175 #if 0
176 SkASSERT(fRestoreOffsetStack.count() > 1);
177 #endif
178
179 // check for underflow
180 if (fRestoreOffsetStack.count() == 0) {
181 return;
182 }
183
184 this->recordRestore();
185
186 fRestoreOffsetStack.pop();
187
188 this->INHERITED::willRestore();
189 }
190
recordRestore(bool fillInSkips)191 void SkPictureRecord::recordRestore(bool fillInSkips) {
192 if (fillInSkips) {
193 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
194 }
195 size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
196 size_t initialOffset = this->addDraw(RESTORE, &size);
197 this->validate(initialOffset, size);
198 }
199
recordTranslate(const SkMatrix & m)200 void SkPictureRecord::recordTranslate(const SkMatrix& m) {
201 SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
202
203 // op + dx + dy
204 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
205 size_t initialOffset = this->addDraw(TRANSLATE, &size);
206 this->addScalar(m.getTranslateX());
207 this->addScalar(m.getTranslateY());
208 this->validate(initialOffset, size);
209 }
210
recordScale(const SkMatrix & m)211 void SkPictureRecord::recordScale(const SkMatrix& m) {
212 SkASSERT(SkMatrix::kScale_Mask == m.getType());
213
214 // op + sx + sy
215 size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
216 size_t initialOffset = this->addDraw(SCALE, &size);
217 this->addScalar(m.getScaleX());
218 this->addScalar(m.getScaleY());
219 this->validate(initialOffset, size);
220 }
221
didConcat44(const SkScalar m[16])222 void SkPictureRecord::didConcat44(const SkScalar m[16]) {
223 this->validate(fWriter.bytesWritten(), 0);
224 // op + matrix
225 size_t size = kUInt32Size + 16 * sizeof(SkScalar);
226 size_t initialOffset = this->addDraw(CONCAT44, &size);
227 fWriter.write(m, 16 * sizeof(SkScalar));
228 this->validate(initialOffset, size);
229
230 this->INHERITED::didConcat44(m);
231 }
232
didScale(SkScalar x,SkScalar y)233 void SkPictureRecord::didScale(SkScalar x, SkScalar y) {
234 this->didConcat(SkMatrix::MakeScale(x, y));
235 }
236
didTranslate(SkScalar x,SkScalar y)237 void SkPictureRecord::didTranslate(SkScalar x, SkScalar y) {
238 this->didConcat(SkMatrix::MakeTrans(x, y));
239 }
240
didConcat(const SkMatrix & matrix)241 void SkPictureRecord::didConcat(const SkMatrix& matrix) {
242 switch (matrix.getType()) {
243 case SkMatrix::kTranslate_Mask:
244 this->recordTranslate(matrix);
245 break;
246 case SkMatrix::kScale_Mask:
247 this->recordScale(matrix);
248 break;
249 default:
250 this->recordConcat(matrix);
251 break;
252 }
253 this->INHERITED::didConcat(matrix);
254 }
255
recordConcat(const SkMatrix & matrix)256 void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
257 this->validate(fWriter.bytesWritten(), 0);
258 // op + matrix
259 size_t size = kUInt32Size + SkMatrixPriv::WriteToMemory(matrix, nullptr);
260 size_t initialOffset = this->addDraw(CONCAT, &size);
261 this->addMatrix(matrix);
262 this->validate(initialOffset, size);
263 }
264
didSetMatrix(const SkMatrix & matrix)265 void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
266 this->validate(fWriter.bytesWritten(), 0);
267 // op + matrix
268 size_t size = kUInt32Size + SkMatrixPriv::WriteToMemory(matrix, nullptr);
269 size_t initialOffset = this->addDraw(SET_MATRIX, &size);
270 this->addMatrix(matrix);
271 this->validate(initialOffset, size);
272 this->INHERITED::didSetMatrix(matrix);
273 }
274
clipOpExpands(SkClipOp op)275 static bool clipOpExpands(SkClipOp op) {
276 switch (op) {
277 case kUnion_SkClipOp:
278 case kXOR_SkClipOp:
279 case kReverseDifference_SkClipOp:
280 case kReplace_SkClipOp:
281 return true;
282 case kIntersect_SkClipOp:
283 case kDifference_SkClipOp:
284 return false;
285 default:
286 SkDEBUGFAIL("unknown clipop");
287 return false;
288 }
289 }
290
fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset)291 void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
292 int32_t offset = fRestoreOffsetStack.top();
293 while (offset > 0) {
294 uint32_t peek = fWriter.readTAt<uint32_t>(offset);
295 fWriter.overwriteTAt(offset, restoreOffset);
296 offset = peek;
297 }
298
299 #ifdef SK_DEBUG
300 // offset of 0 has been disabled, so we skip it
301 if (offset > 0) {
302 // assert that the final offset value points to a save verb
303 uint32_t opSize;
304 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
305 SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
306 }
307 #endif
308 }
309
beginRecording()310 void SkPictureRecord::beginRecording() {
311 // we have to call this *after* our constructor, to ensure that it gets
312 // recorded. This is balanced by restoreToCount() call from endRecording,
313 // which in-turn calls our overridden restore(), so those get recorded too.
314 fInitialSaveCount = this->save();
315 }
316
endRecording()317 void SkPictureRecord::endRecording() {
318 SkASSERT(kNoInitialSave != fInitialSaveCount);
319 this->restoreToCount(fInitialSaveCount);
320 }
321
recordRestoreOffsetPlaceholder(SkClipOp op)322 size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkClipOp op) {
323 if (fRestoreOffsetStack.isEmpty()) {
324 return -1;
325 }
326
327 // The RestoreOffset field is initially filled with a placeholder
328 // value that points to the offset of the previous RestoreOffset
329 // in the current stack level, thus forming a linked list so that
330 // the restore offsets can be filled in when the corresponding
331 // restore command is recorded.
332 int32_t prevOffset = fRestoreOffsetStack.top();
333
334 if (clipOpExpands(op)) {
335 // Run back through any previous clip ops, and mark their offset to
336 // be 0, disabling their ability to trigger a jump-to-restore, otherwise
337 // they could hide this clips ability to expand the clip (i.e. go from
338 // empty to non-empty).
339 this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
340
341 // Reset the pointer back to the previous clip so that subsequent
342 // restores don't overwrite the offsets we just cleared.
343 prevOffset = 0;
344 }
345
346 size_t offset = fWriter.bytesWritten();
347 this->addInt(prevOffset);
348 fRestoreOffsetStack.top() = SkToU32(offset);
349 return offset;
350 }
351
onClipRect(const SkRect & rect,SkClipOp op,ClipEdgeStyle edgeStyle)352 void SkPictureRecord::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
353 this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
354 this->INHERITED::onClipRect(rect, op, edgeStyle);
355 }
356
recordClipRect(const SkRect & rect,SkClipOp op,bool doAA)357 size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkClipOp op, bool doAA) {
358 // id + rect + clip params
359 size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
360 // recordRestoreOffsetPlaceholder doesn't always write an offset
361 if (!fRestoreOffsetStack.isEmpty()) {
362 // + restore offset
363 size += kUInt32Size;
364 }
365 size_t initialOffset = this->addDraw(CLIP_RECT, &size);
366 this->addRect(rect);
367 this->addInt(ClipParams_pack(op, doAA));
368 size_t offset = this->recordRestoreOffsetPlaceholder(op);
369
370 this->validate(initialOffset, size);
371 return offset;
372 }
373
onClipRRect(const SkRRect & rrect,SkClipOp op,ClipEdgeStyle edgeStyle)374 void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
375 this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
376 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
377 }
378
recordClipRRect(const SkRRect & rrect,SkClipOp op,bool doAA)379 size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
380 // op + rrect + clip params
381 size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
382 // recordRestoreOffsetPlaceholder doesn't always write an offset
383 if (!fRestoreOffsetStack.isEmpty()) {
384 // + restore offset
385 size += kUInt32Size;
386 }
387 size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
388 this->addRRect(rrect);
389 this->addInt(ClipParams_pack(op, doAA));
390 size_t offset = recordRestoreOffsetPlaceholder(op);
391 this->validate(initialOffset, size);
392 return offset;
393 }
394
onClipPath(const SkPath & path,SkClipOp op,ClipEdgeStyle edgeStyle)395 void SkPictureRecord::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
396 int pathID = this->addPathToHeap(path);
397 this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
398 this->INHERITED::onClipPath(path, op, edgeStyle);
399 }
400
recordClipPath(int pathID,SkClipOp op,bool doAA)401 size_t SkPictureRecord::recordClipPath(int pathID, SkClipOp op, bool doAA) {
402 // op + path index + clip params
403 size_t size = 3 * kUInt32Size;
404 // recordRestoreOffsetPlaceholder doesn't always write an offset
405 if (!fRestoreOffsetStack.isEmpty()) {
406 // + restore offset
407 size += kUInt32Size;
408 }
409 size_t initialOffset = this->addDraw(CLIP_PATH, &size);
410 this->addInt(pathID);
411 this->addInt(ClipParams_pack(op, doAA));
412 size_t offset = recordRestoreOffsetPlaceholder(op);
413 this->validate(initialOffset, size);
414 return offset;
415 }
416
onClipRegion(const SkRegion & region,SkClipOp op)417 void SkPictureRecord::onClipRegion(const SkRegion& region, SkClipOp op) {
418 this->recordClipRegion(region, op);
419 this->INHERITED::onClipRegion(region, op);
420 }
421
recordClipRegion(const SkRegion & region,SkClipOp op)422 size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkClipOp op) {
423 // op + clip params + region
424 size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
425 // recordRestoreOffsetPlaceholder doesn't always write an offset
426 if (!fRestoreOffsetStack.isEmpty()) {
427 // + restore offset
428 size += kUInt32Size;
429 }
430 size_t initialOffset = this->addDraw(CLIP_REGION, &size);
431 this->addRegion(region);
432 this->addInt(ClipParams_pack(op, false));
433 size_t offset = this->recordRestoreOffsetPlaceholder(op);
434
435 this->validate(initialOffset, size);
436 return offset;
437 }
438
onDrawPaint(const SkPaint & paint)439 void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
440 // op + paint index
441 size_t size = 2 * kUInt32Size;
442 size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
443 this->addPaint(paint);
444 this->validate(initialOffset, size);
445 }
446
onDrawBehind(const SkPaint & paint)447 void SkPictureRecord::onDrawBehind(const SkPaint& paint) {
448 // logically the same as drawPaint, but with a diff enum
449 // op + paint index
450 size_t size = 2 * kUInt32Size;
451 size_t initialOffset = this->addDraw(DRAW_BEHIND_PAINT, &size);
452 this->addPaint(paint);
453 this->validate(initialOffset, size);
454 }
455
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)456 void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
457 const SkPaint& paint) {
458 // op + paint index + mode + count + point data
459 size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
460 size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
461 this->addPaint(paint);
462
463 this->addInt(mode);
464 this->addInt(SkToInt(count));
465 fWriter.writeMul4(pts, count * sizeof(SkPoint));
466 this->validate(initialOffset, size);
467 }
468
onDrawOval(const SkRect & oval,const SkPaint & paint)469 void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
470 // op + paint index + rect
471 size_t size = 2 * kUInt32Size + sizeof(oval);
472 size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
473 this->addPaint(paint);
474 this->addRect(oval);
475 this->validate(initialOffset, size);
476 }
477
onDrawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)478 void SkPictureRecord::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
479 bool useCenter, const SkPaint& paint) {
480 // op + paint index + rect + start + sweep + bool (as int)
481 size_t size = 2 * kUInt32Size + sizeof(oval) + sizeof(startAngle) + sizeof(sweepAngle) +
482 sizeof(int);
483 size_t initialOffset = this->addDraw(DRAW_ARC, &size);
484 this->addPaint(paint);
485 this->addRect(oval);
486 this->addScalar(startAngle);
487 this->addScalar(sweepAngle);
488 this->addInt(useCenter);
489 this->validate(initialOffset, size);
490 }
491
onDrawRect(const SkRect & rect,const SkPaint & paint)492 void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
493 // op + paint index + rect
494 size_t size = 2 * kUInt32Size + sizeof(rect);
495 size_t initialOffset = this->addDraw(DRAW_RECT, &size);
496 this->addPaint(paint);
497 this->addRect(rect);
498 this->validate(initialOffset, size);
499 }
500
onDrawRegion(const SkRegion & region,const SkPaint & paint)501 void SkPictureRecord::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
502 // op + paint index + region
503 size_t regionBytes = region.writeToMemory(nullptr);
504 size_t size = 2 * kUInt32Size + regionBytes;
505 size_t initialOffset = this->addDraw(DRAW_REGION, &size);
506 this->addPaint(paint);
507 fWriter.writeRegion(region);
508 this->validate(initialOffset, size);
509 }
510
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)511 void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
512 // op + paint index + rrect
513 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
514 size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
515 this->addPaint(paint);
516 this->addRRect(rrect);
517 this->validate(initialOffset, size);
518 }
519
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)520 void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
521 const SkPaint& paint) {
522 // op + paint index + rrects
523 size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
524 size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
525 this->addPaint(paint);
526 this->addRRect(outer);
527 this->addRRect(inner);
528 this->validate(initialOffset, size);
529 }
530
onDrawPath(const SkPath & path,const SkPaint & paint)531 void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
532 // op + paint index + path index
533 size_t size = 3 * kUInt32Size;
534 size_t initialOffset = this->addDraw(DRAW_PATH, &size);
535 this->addPaint(paint);
536 this->addPath(path);
537 this->validate(initialOffset, size);
538 }
539
onDrawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)540 void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
541 const SkPaint* paint) {
542 // op + paint_index + image_index + x + y
543 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
544 size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
545 this->addPaintPtr(paint);
546 this->addImage(image);
547 this->addScalar(x);
548 this->addScalar(y);
549 this->validate(initialOffset, size);
550 }
551
onDrawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)552 void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
553 const SkPaint* paint, SrcRectConstraint constraint) {
554 // id + paint_index + image_index + bool_for_src + constraint
555 size_t size = 5 * kUInt32Size;
556 if (src) {
557 size += sizeof(*src); // + rect
558 }
559 size += sizeof(dst); // + rect
560
561 size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
562 this->addPaintPtr(paint);
563 this->addImage(image);
564 this->addRectPtr(src); // may be null
565 this->addRect(dst);
566 this->addInt(constraint);
567 this->validate(initialOffset, size);
568 }
569
onDrawImageNine(const SkImage * img,const SkIRect & center,const SkRect & dst,const SkPaint * paint)570 void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
571 const SkPaint* paint) {
572 // id + paint_index + image_index + center + dst
573 size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
574
575 size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
576 this->addPaintPtr(paint);
577 this->addImage(img);
578 this->addIRect(center);
579 this->addRect(dst);
580 this->validate(initialOffset, size);
581 }
582
onDrawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)583 void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
584 const SkRect& dst, const SkPaint* paint) {
585 size_t latticeSize = SkCanvasPriv::WriteLattice(nullptr, lattice);
586 // op + paint index + image index + lattice + dst rect
587 size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
588 size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
589 this->addPaintPtr(paint);
590 this->addImage(image);
591 (void)SkCanvasPriv::WriteLattice(fWriter.reservePad(latticeSize), lattice);
592 this->addRect(dst);
593 this->validate(initialOffset, size);
594 }
595
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)596 void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
597 const SkPaint& paint) {
598
599 // op + paint index + blob index + x/y
600 size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
601 size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
602
603 this->addPaint(paint);
604 this->addTextBlob(blob);
605 this->addScalar(x);
606 this->addScalar(y);
607
608 this->validate(initialOffset, size);
609 }
610
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)611 void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
612 const SkPaint* paint) {
613 // op + picture index
614 size_t size = 2 * kUInt32Size;
615 size_t initialOffset;
616
617 if (nullptr == matrix && nullptr == paint) {
618 initialOffset = this->addDraw(DRAW_PICTURE, &size);
619 this->addPicture(picture);
620 } else {
621 const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
622 size += SkMatrixPriv::WriteToMemory(m, nullptr) + kUInt32Size; // matrix + paint
623 initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
624 this->addPaintPtr(paint);
625 this->addMatrix(m);
626 this->addPicture(picture);
627 }
628 this->validate(initialOffset, size);
629 }
630
onDrawDrawable(SkDrawable * drawable,const SkMatrix * matrix)631 void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
632 // op + drawable index
633 size_t size = 2 * kUInt32Size;
634 size_t initialOffset;
635
636 if (nullptr == matrix) {
637 initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
638 this->addDrawable(drawable);
639 } else {
640 size += SkMatrixPriv::WriteToMemory(*matrix, nullptr); // matrix
641 initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
642 this->addMatrix(*matrix);
643 this->addDrawable(drawable);
644 }
645 this->validate(initialOffset, size);
646 }
647
onDrawVerticesObject(const SkVertices * vertices,const SkVertices::Bone bones[],int boneCount,SkBlendMode mode,const SkPaint & paint)648 void SkPictureRecord::onDrawVerticesObject(const SkVertices* vertices,
649 const SkVertices::Bone bones[], int boneCount,
650 SkBlendMode mode, const SkPaint& paint) {
651 // op + paint index + vertices index + number of bones + bone matrices + mode
652 size_t size = 5 * kUInt32Size + boneCount * sizeof(SkVertices::Bone);
653 size_t initialOffset = this->addDraw(DRAW_VERTICES_OBJECT, &size);
654
655 this->addPaint(paint);
656 this->addVertices(vertices);
657 this->addInt(boneCount);
658 fWriter.write(bones, boneCount * sizeof(SkVertices::Bone));
659 this->addInt(static_cast<uint32_t>(mode));
660
661 this->validate(initialOffset, size);
662 }
663
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)664 void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
665 const SkPoint texCoords[4], SkBlendMode bmode,
666 const SkPaint& paint) {
667 // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
668 size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
669 uint32_t flag = 0;
670 if (colors) {
671 flag |= DRAW_VERTICES_HAS_COLORS;
672 size += SkPatchUtils::kNumCorners * sizeof(SkColor);
673 }
674 if (texCoords) {
675 flag |= DRAW_VERTICES_HAS_TEXS;
676 size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
677 }
678 if (SkBlendMode::kModulate != bmode) {
679 flag |= DRAW_VERTICES_HAS_XFER;
680 size += kUInt32Size;
681 }
682
683 size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
684 this->addPaint(paint);
685 this->addPatch(cubics);
686 this->addInt(flag);
687
688 // write optional parameters
689 if (colors) {
690 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
691 }
692 if (texCoords) {
693 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
694 }
695 if (flag & DRAW_VERTICES_HAS_XFER) {
696 this->addInt((int)bmode);
697 }
698 this->validate(initialOffset, size);
699 }
700
onDrawAtlas(const SkImage * atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode mode,const SkRect * cull,const SkPaint * paint)701 void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
702 const SkColor colors[], int count, SkBlendMode mode,
703 const SkRect* cull, const SkPaint* paint) {
704 // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
705 size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
706 uint32_t flags = 0;
707 if (colors) {
708 flags |= DRAW_ATLAS_HAS_COLORS;
709 size += count * sizeof(SkColor);
710 size += sizeof(uint32_t); // xfermode::mode
711 }
712 if (cull) {
713 flags |= DRAW_ATLAS_HAS_CULL;
714 size += sizeof(SkRect);
715 }
716
717 size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
718 this->addPaintPtr(paint);
719 this->addImage(atlas);
720 this->addInt(flags);
721 this->addInt(count);
722 fWriter.write(xform, count * sizeof(SkRSXform));
723 fWriter.write(tex, count * sizeof(SkRect));
724
725 // write optional parameters
726 if (colors) {
727 fWriter.write(colors, count * sizeof(SkColor));
728 this->addInt((int)mode);
729 }
730 if (cull) {
731 fWriter.write(cull, sizeof(SkRect));
732 }
733 this->validate(initialOffset, size);
734 }
735
onDrawShadowRec(const SkPath & path,const SkDrawShadowRec & rec)736 void SkPictureRecord::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
737 // op + path index + zParams + lightPos + lightRadius + spot/ambient alphas + color + flags
738 size_t size = 2 * kUInt32Size + 2 * sizeof(SkPoint3) + 1 * sizeof(SkScalar) + 3 * kUInt32Size;
739 size_t initialOffset = this->addDraw(DRAW_SHADOW_REC, &size);
740
741 this->addPath(path);
742
743 fWriter.writePoint3(rec.fZPlaneParams);
744 fWriter.writePoint3(rec.fLightPos);
745 fWriter.writeScalar(rec.fLightRadius);
746 fWriter.write32(rec.fAmbientColor);
747 fWriter.write32(rec.fSpotColor);
748 fWriter.write32(rec.fFlags);
749
750 this->validate(initialOffset, size);
751 }
752
onDrawAnnotation(const SkRect & rect,const char key[],SkData * value)753 void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
754 size_t keyLen = fWriter.WriteStringSize(key);
755 size_t valueLen = fWriter.WriteDataSize(value);
756 size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
757
758 size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
759 this->addRect(rect);
760 fWriter.writeString(key);
761 fWriter.writeData(value);
762 this->validate(initialOffset, size);
763 }
764
onDrawEdgeAAQuad(const SkRect & rect,const SkPoint clip[4],SkCanvas::QuadAAFlags aa,const SkColor4f & color,SkBlendMode mode)765 void SkPictureRecord::onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
766 SkCanvas::QuadAAFlags aa, const SkColor4f& color,
767 SkBlendMode mode) {
768
769 // op + rect + aa flags + color + mode + hasClip(as int) + clipCount*points
770 size_t size = 4 * kUInt32Size + sizeof(SkColor4f) + sizeof(rect) +
771 (clip ? 4 : 0) * sizeof(SkPoint);
772 size_t initialOffset = this->addDraw(DRAW_EDGEAA_QUAD, &size);
773 this->addRect(rect);
774 this->addInt((int) aa);
775 fWriter.write(&color, sizeof(SkColor4f));
776 this->addInt((int) mode);
777 this->addInt(clip != nullptr);
778 if (clip) {
779 this->addPoints(clip, 4);
780 }
781 this->validate(initialOffset, size);
782 }
783
onDrawEdgeAAImageSet(const SkCanvas::ImageSetEntry set[],int count,const SkPoint dstClips[],const SkMatrix preViewMatrices[],const SkPaint * paint,SkCanvas::SrcRectConstraint constraint)784 void SkPictureRecord::onDrawEdgeAAImageSet(const SkCanvas::ImageSetEntry set[], int count,
785 const SkPoint dstClips[],
786 const SkMatrix preViewMatrices[],
787 const SkPaint* paint,
788 SkCanvas::SrcRectConstraint constraint) {
789 static constexpr size_t kMatrixSize = 9 * sizeof(SkScalar); // *not* sizeof(SkMatrix)
790 // op + count + paint + constraint + (image index, src rect, dst rect, alpha, aa flags,
791 // hasClip(int), matrixIndex) * cnt + totalClipCount + dstClips + totalMatrixCount + matrices
792 int totalDstClipCount, totalMatrixCount;
793 SkCanvasPriv::GetDstClipAndMatrixCounts(set, count, &totalDstClipCount, &totalMatrixCount);
794
795 size_t size = 6 * kUInt32Size + sizeof(SkPoint) * totalDstClipCount +
796 kMatrixSize * totalMatrixCount +
797 (4 * kUInt32Size + 2 * sizeof(SkRect) + sizeof(SkScalar)) * count;
798 size_t initialOffset = this->addDraw(DRAW_EDGEAA_IMAGE_SET, &size);
799 this->addInt(count);
800 this->addPaintPtr(paint);
801 this->addInt((int) constraint);
802 for (int i = 0; i < count; ++i) {
803 this->addImage(set[i].fImage.get());
804 this->addRect(set[i].fSrcRect);
805 this->addRect(set[i].fDstRect);
806 this->addInt(set[i].fMatrixIndex);
807 this->addScalar(set[i].fAlpha);
808 this->addInt((int)set[i].fAAFlags);
809 this->addInt(set[i].fHasClip);
810 }
811 this->addInt(totalDstClipCount);
812 this->addPoints(dstClips, totalDstClipCount);
813 this->addInt(totalMatrixCount);
814 for (int i = 0; i < totalMatrixCount; ++i) {
815 this->addMatrix(preViewMatrices[i]);
816 }
817 this->validate(initialOffset, size);
818 }
819
820 ///////////////////////////////////////////////////////////////////////////////
821
822 // De-duping helper.
823
824 template <typename T>
equals(T * a,T * b)825 static bool equals(T* a, T* b) { return a->uniqueID() == b->uniqueID(); }
826
827 template <>
equals(SkDrawable * a,SkDrawable * b)828 bool equals(SkDrawable* a, SkDrawable* b) {
829 // SkDrawable's generationID is not a stable unique identifier.
830 return a == b;
831 }
832
833 template <typename T>
find_or_append(SkTArray<sk_sp<T>> & array,T * obj)834 static int find_or_append(SkTArray<sk_sp<T>>& array, T* obj) {
835 for (int i = 0; i < array.count(); i++) {
836 if (equals(array[i].get(), obj)) {
837 return i;
838 }
839 }
840
841 array.push_back(sk_ref_sp(obj));
842
843 return array.count() - 1;
844 }
845
onNewSurface(const SkImageInfo & info,const SkSurfaceProps &)846 sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
847 return nullptr;
848 }
849
addImage(const SkImage * image)850 void SkPictureRecord::addImage(const SkImage* image) {
851 // convention for images is 0-based index
852 this->addInt(find_or_append(fImages, image));
853 }
854
addMatrix(const SkMatrix & matrix)855 void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
856 fWriter.writeMatrix(matrix);
857 }
858
addPaintPtr(const SkPaint * paint)859 void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
860 if (paint) {
861 fPaints.push_back(*paint);
862 this->addInt(fPaints.count());
863 } else {
864 this->addInt(0);
865 }
866 }
867
addPathToHeap(const SkPath & path)868 int SkPictureRecord::addPathToHeap(const SkPath& path) {
869 if (int* n = fPaths.find(path)) {
870 return *n;
871 }
872 int n = fPaths.count() + 1; // 0 is reserved for null / error.
873 fPaths.set(path, n);
874 return n;
875 }
876
addPath(const SkPath & path)877 void SkPictureRecord::addPath(const SkPath& path) {
878 this->addInt(this->addPathToHeap(path));
879 }
880
addPatch(const SkPoint cubics[12])881 void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
882 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
883 }
884
addPicture(const SkPicture * picture)885 void SkPictureRecord::addPicture(const SkPicture* picture) {
886 // follow the convention of recording a 1-based index
887 this->addInt(find_or_append(fPictures, picture) + 1);
888 }
889
addDrawable(SkDrawable * drawable)890 void SkPictureRecord::addDrawable(SkDrawable* drawable) {
891 // follow the convention of recording a 1-based index
892 this->addInt(find_or_append(fDrawables, drawable) + 1);
893 }
894
addPoint(const SkPoint & point)895 void SkPictureRecord::addPoint(const SkPoint& point) {
896 fWriter.writePoint(point);
897 }
898
addPoints(const SkPoint pts[],int count)899 void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
900 fWriter.writeMul4(pts, count * sizeof(SkPoint));
901 }
902
addNoOp()903 void SkPictureRecord::addNoOp() {
904 size_t size = kUInt32Size; // op
905 this->addDraw(NOOP, &size);
906 }
907
addRect(const SkRect & rect)908 void SkPictureRecord::addRect(const SkRect& rect) {
909 fWriter.writeRect(rect);
910 }
911
addRectPtr(const SkRect * rect)912 void SkPictureRecord::addRectPtr(const SkRect* rect) {
913 if (fWriter.writeBool(rect != nullptr)) {
914 fWriter.writeRect(*rect);
915 }
916 }
917
addIRect(const SkIRect & rect)918 void SkPictureRecord::addIRect(const SkIRect& rect) {
919 fWriter.write(&rect, sizeof(rect));
920 }
921
addIRectPtr(const SkIRect * rect)922 void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
923 if (fWriter.writeBool(rect != nullptr)) {
924 *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
925 }
926 }
927
addRRect(const SkRRect & rrect)928 void SkPictureRecord::addRRect(const SkRRect& rrect) {
929 fWriter.writeRRect(rrect);
930 }
931
addRegion(const SkRegion & region)932 void SkPictureRecord::addRegion(const SkRegion& region) {
933 fWriter.writeRegion(region);
934 }
935
addText(const void * text,size_t byteLength)936 void SkPictureRecord::addText(const void* text, size_t byteLength) {
937 addInt(SkToInt(byteLength));
938 fWriter.writePad(text, byteLength);
939 }
940
addTextBlob(const SkTextBlob * blob)941 void SkPictureRecord::addTextBlob(const SkTextBlob* blob) {
942 // follow the convention of recording a 1-based index
943 this->addInt(find_or_append(fTextBlobs, blob) + 1);
944 }
945
addVertices(const SkVertices * vertices)946 void SkPictureRecord::addVertices(const SkVertices* vertices) {
947 // follow the convention of recording a 1-based index
948 this->addInt(find_or_append(fVertices, vertices) + 1);
949 }
950
951 ///////////////////////////////////////////////////////////////////////////////
952