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