Flutter Engine
The Flutter Engine
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
56 : SkPictureRecord(SkIRect::MakeSize(dimensions), flags) {}
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
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
261 this->didConcat44(SkM44::Scale(x, y));
262}
263
265 this->didConcat44(SkM44::Translate(x, y));
266}
267
269 this->validate(fWriter.bytesWritten(), 0);
270 // op + matrix
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);
329}
330
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);
351}
352
354 // op + rrect + clip params
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);
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
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
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
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
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
669 uint32_t flag = 0;
670 if (colors) {
673 }
674 if (texCoords) {
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);
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
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
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[],
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 +
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
854 return nullptr;
855}
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
Definition: FontMgrTest.cpp:50
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkBlendMode
Definition: SkBlendMode.h:38
@ kModulate
r = s*d
SkClipOp
Definition: SkClipOp.h:13
SkRGBA4f< kUnpremul_SkAlphaType > SkColor4f
Definition: SkColor.h:426
uint32_t SkColor
Definition: SkColor.h:37
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
@ SAVEBEHIND_HAS_SUBSET
@ DRAW_EDGEAA_QUAD
@ DRAW_PATH
Definition: SkPictureFlat.h:47
@ RESTORE
Definition: SkPictureFlat.h:61
@ SET_M44
@ CLIP_PATH
Definition: SkPictureFlat.h:34
@ DRAW_PAINT
Definition: SkPictureFlat.h:46
@ DRAW_SLUG
@ DRAW_PICTURE_MATRIX_PAINT
Definition: SkPictureFlat.h:80
@ DRAW_REGION
@ DRAW_DRAWABLE
Definition: SkPictureFlat.h:92
@ DRAW_IMAGE_RECT2
@ DRAW_IMAGE2
@ DRAW_RRECT
Definition: SkPictureFlat.h:55
@ DRAW_DRRECT
Definition: SkPictureFlat.h:75
@ SCALE
Definition: SkPictureFlat.h:65
@ DRAW_PATCH
Definition: SkPictureFlat.h:79
@ DRAW_BEHIND_PAINT
@ DRAW_EDGEAA_IMAGE_SET2
@ DRAW_TEXT_BLOB
Definition: SkPictureFlat.h:81
@ DRAW_PICTURE
Definition: SkPictureFlat.h:48
@ CONCAT44
@ NOOP
Definition: SkPictureFlat.h:69
@ SAVE
Definition: SkPictureFlat.h:63
@ RESET_CLIP
@ DRAW_DRAWABLE_MATRIX
Definition: SkPictureFlat.h:93
@ DRAW_ARC
@ DRAW_RECT
Definition: SkPictureFlat.h:54
@ DRAW_VERTICES_OBJECT
@ DRAW_ANNOTATION
Definition: SkPictureFlat.h:91
@ CONCAT
Definition: SkPictureFlat.h:38
@ SAVE_BEHIND
@ DRAW_POINTS
Definition: SkPictureFlat.h:49
@ DRAW_SHADOW_REC
Definition: SkPictureFlat.h:98
@ SAVE_LAYER_SAVELAYERREC
Definition: SkPictureFlat.h:89
@ DRAW_ATLAS
Definition: SkPictureFlat.h:84
@ CLIP_RRECT
Definition: SkPictureFlat.h:37
@ TRANSLATE
Definition: SkPictureFlat.h:68
@ DRAW_OVAL
Definition: SkPictureFlat.h:45
@ CLIP_REGION
Definition: SkPictureFlat.h:35
@ CLIP_SHADER_IN_PAINT
@ CLIP_RECT
Definition: SkPictureFlat.h:36
@ 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
static void WriteLattice(SkWriteBuffer &, const SkCanvas::Lattice &)
static SkScalar GetBackdropScaleFactor(const SkCanvas::SaveLayerRec &rec)
Definition: SkCanvasPriv.h:85
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:478
int save()
Definition: SkCanvas.cpp:447
@ kSoft_ClipEdgeStyle
Definition: SkCanvas.h:2337
friend class SkPictureRecord
Definition: SkCanvas.h:2493
Definition: SkData.h:25
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)
Definition: SkMatrixPriv.h:30
static const SkScalar * M44ColMajor(const SkM44 &m)
Definition: SkMatrixPriv.h:185
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
@ kTranslate_Mask
translation SkMatrix
Definition: SkMatrix.h:193
@ kScale_Mask
scale SkMatrix
Definition: SkMatrix.h:194
Definition: SkPath.h:59
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
Definition: SkRegion.cpp:1149
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)
Definition: SkWriter32.cpp:24
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)
Definition: SkWriter32.cpp:18
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)
Definition: SkWriter32.cpp:55
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)
Definition: SkWriter32.cpp:38
size_t bytesWritten() const
Definition: SkWriter32.h:48
int size() const
Definition: SkTArray.h:421
int count() const
Definition: SkTHash.h:471
V * find(const K &key) const
Definition: SkTHash.h:494
V * set(K key, V val)
Definition: SkTHash.h:487
const Paint & paint
Definition: color_source.cc:38
DlColor color
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
sk_sp< const SkImage > atlas
Definition: SkRecords.h:331
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
PODArray< SkPoint > dstClips
Definition: SkRecords.h:364
sk_sp< const SkImage > image
Definition: SkRecords.h:269
ClipOpAndAA opAA SkRegion region
Definition: SkRecords.h:238
sk_sp< const SkPicture > picture
Definition: SkRecords.h:299
SkRRect rrect
Definition: SkRecords.h:232
SkRect oval
Definition: SkRecords.h:249
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
PODArray< SkMatrix > preViewMatrices
Definition: SkRecords.h:365
SkScalar startAngle
Definition: SkRecords.h:250
SkScalar sweepAngle
Definition: SkRecords.h:251
PODArray< SkColor > colors
Definition: SkRecords.h:276
SkSamplingOptions sampling
Definition: SkRecords.h:337
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
Definition: switches.h:76
dst
Definition: cp.py:12
const myers::Point & get(const myers::Segment &)
#define T
Definition: precompiler.cc:65
SeparatedVector2 offset
FilterSpan fFilters
Definition: SkCanvas.h:745
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
SkPoint3 fZPlaneParams
Definition: SkRect.h:32
Definition: SkSize.h:16
SkISize dimensions() const
Definition: SkImageInfo.h:421