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