1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2014 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 "include/core/SkCanvas.h"
9cb93a386Sopenharmony_ci#include "include/core/SkRSXform.h"
10cb93a386Sopenharmony_ci#include "include/core/SkTextBlob.h"
11cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
12cb93a386Sopenharmony_ci#include "include/private/SkTDArray.h"
13cb93a386Sopenharmony_ci#include "src/core/SkCanvasPriv.h"
14cb93a386Sopenharmony_ci#include "src/core/SkDrawShadowInfo.h"
15cb93a386Sopenharmony_ci#include "src/core/SkFontPriv.h"
16cb93a386Sopenharmony_ci#include "src/core/SkPaintPriv.h"
17cb93a386Sopenharmony_ci#include "src/core/SkPictureData.h"
18cb93a386Sopenharmony_ci#include "src/core/SkPicturePlayback.h"
19cb93a386Sopenharmony_ci#include "src/core/SkPictureRecord.h"
20cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h"
21cb93a386Sopenharmony_ci#include "src/core/SkSafeMath.h"
22cb93a386Sopenharmony_ci#include "src/core/SkSamplingPriv.h"
23cb93a386Sopenharmony_ci#include "src/core/SkVerticesPriv.h"
24cb93a386Sopenharmony_ci#include "src/utils/SkPatchUtils.h"
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_cistatic const SkRect* get_rect_ptr(SkReadBuffer* reader, SkRect* storage) {
27cb93a386Sopenharmony_ci    if (reader->readBool()) {
28cb93a386Sopenharmony_ci        reader->readRect(storage);
29cb93a386Sopenharmony_ci        return storage;
30cb93a386Sopenharmony_ci    } else {
31cb93a386Sopenharmony_ci        return nullptr;
32cb93a386Sopenharmony_ci    }
33cb93a386Sopenharmony_ci}
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_civoid SkPicturePlayback::draw(SkCanvas* canvas,
36cb93a386Sopenharmony_ci                             SkPicture::AbortCallback* callback,
37cb93a386Sopenharmony_ci                             SkReadBuffer* buffer) {
38cb93a386Sopenharmony_ci    AutoResetOpID aroi(this);
39cb93a386Sopenharmony_ci    SkASSERT(0 == fCurOffset);
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_ci    SkReadBuffer reader(fPictureData->opData()->bytes(),
42cb93a386Sopenharmony_ci                        fPictureData->opData()->size());
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci    // Record this, so we can concat w/ it if we encounter a setMatrix()
45cb93a386Sopenharmony_ci    SkM44 initialMatrix = canvas->getLocalToDevice();
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ci    SkAutoCanvasRestore acr(canvas, false);
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    while (!reader.eof() && reader.isValid()) {
50cb93a386Sopenharmony_ci        if (callback && callback->abort()) {
51cb93a386Sopenharmony_ci            return;
52cb93a386Sopenharmony_ci        }
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ci        fCurOffset = reader.offset();
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci        uint32_t bits = reader.readInt();
57cb93a386Sopenharmony_ci        uint32_t op   = bits >> 24,
58cb93a386Sopenharmony_ci                 size = bits & 0xffffff;
59cb93a386Sopenharmony_ci        if (size == 0xffffff) {
60cb93a386Sopenharmony_ci            size = reader.readInt();
61cb93a386Sopenharmony_ci        }
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci        if (!reader.validate(size > 0 && op > UNUSED && op <= LAST_DRAWTYPE_ENUM)) {
64cb93a386Sopenharmony_ci            return;
65cb93a386Sopenharmony_ci        }
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ci        this->handleOp(&reader, (DrawType)op, size, canvas, initialMatrix);
68cb93a386Sopenharmony_ci    }
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    // need to propagate invalid state to the parent reader
71cb93a386Sopenharmony_ci    if (buffer) {
72cb93a386Sopenharmony_ci        buffer->validate(reader.isValid());
73cb93a386Sopenharmony_ci    }
74cb93a386Sopenharmony_ci}
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_cistatic void validate_offsetToRestore(SkReadBuffer* reader, size_t offsetToRestore) {
77cb93a386Sopenharmony_ci    if (offsetToRestore) {
78cb93a386Sopenharmony_ci        reader->validate(SkIsAlign4(offsetToRestore) && offsetToRestore >= reader->offset());
79cb93a386Sopenharmony_ci    }
80cb93a386Sopenharmony_ci}
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_cistatic bool do_clip_op(SkReadBuffer* reader, SkCanvas* canvas, SkRegion::Op op,
83cb93a386Sopenharmony_ci                       SkClipOp* clipOpToUse) {
84cb93a386Sopenharmony_ci    switch(op) {
85cb93a386Sopenharmony_ci        case SkRegion::kDifference_Op:
86cb93a386Sopenharmony_ci        case SkRegion::kIntersect_Op:
87cb93a386Sopenharmony_ci            // Fully supported, identity mapping between SkClipOp and Region::Op
88cb93a386Sopenharmony_ci            *clipOpToUse = static_cast<SkClipOp>(op);
89cb93a386Sopenharmony_ci            return true;
90cb93a386Sopenharmony_ci        case SkRegion::kReplace_Op:
91cb93a386Sopenharmony_ci            // Emulate the replace by resetting first and following it up with an intersect
92cb93a386Sopenharmony_ci            SkASSERT(reader->isVersionLT(SkPicturePriv::kNoExpandingClipOps));
93cb93a386Sopenharmony_ci            SkCanvasPriv::ResetClip(canvas);
94cb93a386Sopenharmony_ci            *clipOpToUse = SkClipOp::kIntersect;
95cb93a386Sopenharmony_ci            return true;
96cb93a386Sopenharmony_ci        default:
97cb93a386Sopenharmony_ci            // An expanding clip op, which if encountered on an old SKP, we just silently ignore
98cb93a386Sopenharmony_ci            SkASSERT(reader->isVersionLT(SkPicturePriv::kNoExpandingClipOps));
99cb93a386Sopenharmony_ci            return false;
100cb93a386Sopenharmony_ci    }
101cb93a386Sopenharmony_ci}
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_civoid SkPicturePlayback::handleOp(SkReadBuffer* reader,
104cb93a386Sopenharmony_ci                                 DrawType op,
105cb93a386Sopenharmony_ci                                 uint32_t size,
106cb93a386Sopenharmony_ci                                 SkCanvas* canvas,
107cb93a386Sopenharmony_ci                                 const SkM44& initialMatrix) {
108cb93a386Sopenharmony_ci#define BREAK_ON_READ_ERROR(r)  if (!r->isValid()) break
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_ci    switch (op) {
111cb93a386Sopenharmony_ci        case NOOP: {
112cb93a386Sopenharmony_ci            SkASSERT(size >= 4);
113cb93a386Sopenharmony_ci            reader->skip(size - 4);
114cb93a386Sopenharmony_ci        } break;
115cb93a386Sopenharmony_ci        case FLUSH:
116cb93a386Sopenharmony_ci            canvas->flush();
117cb93a386Sopenharmony_ci            break;
118cb93a386Sopenharmony_ci        case CLIP_PATH: {
119cb93a386Sopenharmony_ci            const SkPath& path = fPictureData->getPath(reader);
120cb93a386Sopenharmony_ci            uint32_t packed = reader->readInt();
121cb93a386Sopenharmony_ci            SkRegion::Op rgnOp = ClipParams_unpackRegionOp(reader, packed);
122cb93a386Sopenharmony_ci            bool doAA = ClipParams_unpackDoAA(packed);
123cb93a386Sopenharmony_ci            size_t offsetToRestore = reader->readInt();
124cb93a386Sopenharmony_ci            validate_offsetToRestore(reader, offsetToRestore);
125cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_ci            SkClipOp clipOp;
128cb93a386Sopenharmony_ci            if (do_clip_op(reader, canvas, rgnOp, &clipOp)) {
129cb93a386Sopenharmony_ci                canvas->clipPath(path, clipOp, doAA);
130cb93a386Sopenharmony_ci            }
131cb93a386Sopenharmony_ci            if (canvas->isClipEmpty() && offsetToRestore) {
132cb93a386Sopenharmony_ci                reader->skip(offsetToRestore - reader->offset());
133cb93a386Sopenharmony_ci            }
134cb93a386Sopenharmony_ci        } break;
135cb93a386Sopenharmony_ci        case CLIP_REGION: {
136cb93a386Sopenharmony_ci            SkRegion region;
137cb93a386Sopenharmony_ci            reader->readRegion(&region);
138cb93a386Sopenharmony_ci            uint32_t packed = reader->readInt();
139cb93a386Sopenharmony_ci            SkRegion::Op rgnOp = ClipParams_unpackRegionOp(reader, packed);
140cb93a386Sopenharmony_ci            size_t offsetToRestore = reader->readInt();
141cb93a386Sopenharmony_ci            validate_offsetToRestore(reader, offsetToRestore);
142cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ci            SkClipOp clipOp;
145cb93a386Sopenharmony_ci            if (do_clip_op(reader, canvas, rgnOp, &clipOp)) {
146cb93a386Sopenharmony_ci                canvas->clipRegion(region, clipOp);
147cb93a386Sopenharmony_ci            }
148cb93a386Sopenharmony_ci            if (canvas->isClipEmpty() && offsetToRestore) {
149cb93a386Sopenharmony_ci                reader->skip(offsetToRestore - reader->offset());
150cb93a386Sopenharmony_ci            }
151cb93a386Sopenharmony_ci        } break;
152cb93a386Sopenharmony_ci        case CLIP_RECT: {
153cb93a386Sopenharmony_ci            SkRect rect;
154cb93a386Sopenharmony_ci            reader->readRect(&rect);
155cb93a386Sopenharmony_ci            uint32_t packed = reader->readInt();
156cb93a386Sopenharmony_ci            SkRegion::Op rgnOp = ClipParams_unpackRegionOp(reader, packed);
157cb93a386Sopenharmony_ci            bool doAA = ClipParams_unpackDoAA(packed);
158cb93a386Sopenharmony_ci            size_t offsetToRestore = reader->readInt();
159cb93a386Sopenharmony_ci            validate_offsetToRestore(reader, offsetToRestore);
160cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
161cb93a386Sopenharmony_ci
162cb93a386Sopenharmony_ci            SkClipOp clipOp;
163cb93a386Sopenharmony_ci            if (do_clip_op(reader, canvas, rgnOp, &clipOp)) {
164cb93a386Sopenharmony_ci                canvas->clipRect(rect, clipOp, doAA);
165cb93a386Sopenharmony_ci            }
166cb93a386Sopenharmony_ci            if (canvas->isClipEmpty() && offsetToRestore) {
167cb93a386Sopenharmony_ci                reader->skip(offsetToRestore - reader->offset());
168cb93a386Sopenharmony_ci            }
169cb93a386Sopenharmony_ci        } break;
170cb93a386Sopenharmony_ci        case CLIP_RRECT: {
171cb93a386Sopenharmony_ci            SkRRect rrect;
172cb93a386Sopenharmony_ci            reader->readRRect(&rrect);
173cb93a386Sopenharmony_ci            uint32_t packed = reader->readInt();
174cb93a386Sopenharmony_ci            SkRegion::Op rgnOp = ClipParams_unpackRegionOp(reader, packed);
175cb93a386Sopenharmony_ci            bool doAA = ClipParams_unpackDoAA(packed);
176cb93a386Sopenharmony_ci            size_t offsetToRestore = reader->readInt();
177cb93a386Sopenharmony_ci            validate_offsetToRestore(reader, offsetToRestore);
178cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
179cb93a386Sopenharmony_ci
180cb93a386Sopenharmony_ci            SkClipOp clipOp;
181cb93a386Sopenharmony_ci            if (do_clip_op(reader, canvas, rgnOp, &clipOp)) {
182cb93a386Sopenharmony_ci                canvas->clipRRect(rrect, clipOp, doAA);
183cb93a386Sopenharmony_ci            }
184cb93a386Sopenharmony_ci            if (canvas->isClipEmpty() && offsetToRestore) {
185cb93a386Sopenharmony_ci                reader->skip(offsetToRestore - reader->offset());
186cb93a386Sopenharmony_ci            }
187cb93a386Sopenharmony_ci        } break;
188cb93a386Sopenharmony_ci        case CLIP_SHADER_IN_PAINT: {
189cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
190cb93a386Sopenharmony_ci            // clipShader() was never used in conjunction with deprecated, expanding clip ops, so
191cb93a386Sopenharmony_ci            // it requires the op to just be intersect or difference.
192cb93a386Sopenharmony_ci            SkClipOp clipOp = reader->checkRange(SkClipOp::kDifference, SkClipOp::kIntersect);
193cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
194cb93a386Sopenharmony_ci
195cb93a386Sopenharmony_ci            canvas->clipShader(paint.refShader(), clipOp);
196cb93a386Sopenharmony_ci        } break;
197cb93a386Sopenharmony_ci        case RESET_CLIP:
198cb93a386Sopenharmony_ci            // For Android, an emulated "replace" clip op appears as a manual reset followed by
199cb93a386Sopenharmony_ci            // an intersect operation (equivalent to the above handling of replace ops encountered
200cb93a386Sopenharmony_ci            // in old serialized pictures).
201cb93a386Sopenharmony_ci            SkCanvasPriv::ResetClip(canvas);
202cb93a386Sopenharmony_ci            break;
203cb93a386Sopenharmony_ci        case PUSH_CULL: break;  // Deprecated, safe to ignore both push and pop.
204cb93a386Sopenharmony_ci        case POP_CULL:  break;
205cb93a386Sopenharmony_ci        case CONCAT: {
206cb93a386Sopenharmony_ci            SkMatrix matrix;
207cb93a386Sopenharmony_ci            reader->readMatrix(&matrix);
208cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
209cb93a386Sopenharmony_ci
210cb93a386Sopenharmony_ci            canvas->concat(matrix);
211cb93a386Sopenharmony_ci            break;
212cb93a386Sopenharmony_ci        }
213cb93a386Sopenharmony_ci        case CONCAT44: {
214cb93a386Sopenharmony_ci            const SkScalar* colMaj = reader->skipT<SkScalar>(16);
215cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
216cb93a386Sopenharmony_ci            canvas->concat(SkM44::ColMajor(colMaj));
217cb93a386Sopenharmony_ci            break;
218cb93a386Sopenharmony_ci        }
219cb93a386Sopenharmony_ci        case DRAW_ANNOTATION: {
220cb93a386Sopenharmony_ci            SkRect rect;
221cb93a386Sopenharmony_ci            reader->readRect(&rect);
222cb93a386Sopenharmony_ci            SkString key;
223cb93a386Sopenharmony_ci            reader->readString(&key);
224cb93a386Sopenharmony_ci            sk_sp<SkData> data = reader->readByteArrayAsData();
225cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
226cb93a386Sopenharmony_ci            SkASSERT(data);
227cb93a386Sopenharmony_ci
228cb93a386Sopenharmony_ci            canvas->drawAnnotation(rect, key.c_str(), data.get());
229cb93a386Sopenharmony_ci        } break;
230cb93a386Sopenharmony_ci        case DRAW_ARC: {
231cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
232cb93a386Sopenharmony_ci            SkRect rect;
233cb93a386Sopenharmony_ci            reader->readRect(&rect);
234cb93a386Sopenharmony_ci            SkScalar startAngle = reader->readScalar();
235cb93a386Sopenharmony_ci            SkScalar sweepAngle = reader->readScalar();
236cb93a386Sopenharmony_ci            int useCenter = reader->readInt();
237cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
238cb93a386Sopenharmony_ci
239cb93a386Sopenharmony_ci            canvas->drawArc(rect, startAngle, sweepAngle, SkToBool(useCenter), paint);
240cb93a386Sopenharmony_ci        } break;
241cb93a386Sopenharmony_ci        case DRAW_ATLAS: {
242cb93a386Sopenharmony_ci            const SkPaint* paint = fPictureData->optionalPaint(reader);
243cb93a386Sopenharmony_ci            const SkImage* atlas = fPictureData->getImage(reader);
244cb93a386Sopenharmony_ci            const uint32_t flags = reader->readUInt();
245cb93a386Sopenharmony_ci            const int count = reader->readUInt();
246cb93a386Sopenharmony_ci            const SkRSXform* xform = (const SkRSXform*)reader->skip(count, sizeof(SkRSXform));
247cb93a386Sopenharmony_ci            const SkRect* tex = (const SkRect*)reader->skip(count, sizeof(SkRect));
248cb93a386Sopenharmony_ci            const SkColor* colors = nullptr;
249cb93a386Sopenharmony_ci            SkBlendMode mode = SkBlendMode::kDst;
250cb93a386Sopenharmony_ci            if (flags & DRAW_ATLAS_HAS_COLORS) {
251cb93a386Sopenharmony_ci                colors = (const SkColor*)reader->skip(count, sizeof(SkColor));
252cb93a386Sopenharmony_ci                mode = (SkBlendMode)reader->readUInt();
253cb93a386Sopenharmony_ci            }
254cb93a386Sopenharmony_ci            const SkRect* cull = nullptr;
255cb93a386Sopenharmony_ci            if (flags & DRAW_ATLAS_HAS_CULL) {
256cb93a386Sopenharmony_ci                cull = (const SkRect*)reader->skip(sizeof(SkRect));
257cb93a386Sopenharmony_ci            }
258cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
259cb93a386Sopenharmony_ci
260cb93a386Sopenharmony_ci            SkSamplingOptions sampling;
261cb93a386Sopenharmony_ci            if (flags & DRAW_ATLAS_HAS_SAMPLING) {
262cb93a386Sopenharmony_ci                sampling = reader->readSampling();
263cb93a386Sopenharmony_ci                BREAK_ON_READ_ERROR(reader);
264cb93a386Sopenharmony_ci            }
265cb93a386Sopenharmony_ci            canvas->drawAtlas(atlas, xform, tex, colors, count, mode, sampling, cull, paint);
266cb93a386Sopenharmony_ci        } break;
267cb93a386Sopenharmony_ci        case DRAW_CLEAR: {
268cb93a386Sopenharmony_ci            auto c = reader->readInt();
269cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
270cb93a386Sopenharmony_ci
271cb93a386Sopenharmony_ci            canvas->clear(c);
272cb93a386Sopenharmony_ci        } break;
273cb93a386Sopenharmony_ci        case DRAW_DATA: {
274cb93a386Sopenharmony_ci            // This opcode is now dead, just need to skip it for backwards compatibility
275cb93a386Sopenharmony_ci            size_t length = reader->readInt();
276cb93a386Sopenharmony_ci            (void)reader->skip(length);
277cb93a386Sopenharmony_ci            // skip handles padding the read out to a multiple of 4
278cb93a386Sopenharmony_ci        } break;
279cb93a386Sopenharmony_ci        case DRAW_DRAWABLE: {
280cb93a386Sopenharmony_ci            auto* d = fPictureData->getDrawable(reader);
281cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
282cb93a386Sopenharmony_ci
283cb93a386Sopenharmony_ci            canvas->drawDrawable(d);
284cb93a386Sopenharmony_ci        } break;
285cb93a386Sopenharmony_ci        case DRAW_DRAWABLE_MATRIX: {
286cb93a386Sopenharmony_ci            SkMatrix matrix;
287cb93a386Sopenharmony_ci            reader->readMatrix(&matrix);
288cb93a386Sopenharmony_ci            SkDrawable* drawable = fPictureData->getDrawable(reader);
289cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
290cb93a386Sopenharmony_ci
291cb93a386Sopenharmony_ci            canvas->drawDrawable(drawable, &matrix);
292cb93a386Sopenharmony_ci        } break;
293cb93a386Sopenharmony_ci        case DRAW_DRRECT: {
294cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
295cb93a386Sopenharmony_ci            SkRRect outer, inner;
296cb93a386Sopenharmony_ci            reader->readRRect(&outer);
297cb93a386Sopenharmony_ci            reader->readRRect(&inner);
298cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
299cb93a386Sopenharmony_ci
300cb93a386Sopenharmony_ci            canvas->drawDRRect(outer, inner, paint);
301cb93a386Sopenharmony_ci        } break;
302cb93a386Sopenharmony_ci        case DRAW_EDGEAA_QUAD: {
303cb93a386Sopenharmony_ci            SkRect rect;
304cb93a386Sopenharmony_ci            reader->readRect(&rect);
305cb93a386Sopenharmony_ci            SkCanvas::QuadAAFlags aaFlags = static_cast<SkCanvas::QuadAAFlags>(reader->read32());
306cb93a386Sopenharmony_ci            SkColor4f color;
307cb93a386Sopenharmony_ci            reader->readColor4f(&color);
308cb93a386Sopenharmony_ci            SkBlendMode blend = static_cast<SkBlendMode>(reader->read32());
309cb93a386Sopenharmony_ci            bool hasClip = reader->readInt();
310cb93a386Sopenharmony_ci            SkPoint* clip = nullptr;
311cb93a386Sopenharmony_ci            if (hasClip) {
312cb93a386Sopenharmony_ci                clip = (SkPoint*) reader->skip(4, sizeof(SkPoint));
313cb93a386Sopenharmony_ci            }
314cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
315cb93a386Sopenharmony_ci            canvas->experimental_DrawEdgeAAQuad(rect, clip, aaFlags, color, blend);
316cb93a386Sopenharmony_ci        } break;
317cb93a386Sopenharmony_ci        case DRAW_EDGEAA_IMAGE_SET:
318cb93a386Sopenharmony_ci        case DRAW_EDGEAA_IMAGE_SET2: {
319cb93a386Sopenharmony_ci            static const size_t kEntryReadSize =
320cb93a386Sopenharmony_ci                    4 * sizeof(uint32_t) + 2 * sizeof(SkRect) + sizeof(SkScalar);
321cb93a386Sopenharmony_ci            static const size_t kMatrixSize = 9 * sizeof(SkScalar); // != sizeof(SkMatrix)
322cb93a386Sopenharmony_ci
323cb93a386Sopenharmony_ci            int cnt = reader->readInt();
324cb93a386Sopenharmony_ci            if (!reader->validate(cnt >= 0)) {
325cb93a386Sopenharmony_ci                break;
326cb93a386Sopenharmony_ci            }
327cb93a386Sopenharmony_ci            const SkPaint* paint = fPictureData->optionalPaint(reader);
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_ci            SkSamplingOptions sampling;
330cb93a386Sopenharmony_ci            if (op == DRAW_EDGEAA_IMAGE_SET2) {
331cb93a386Sopenharmony_ci                sampling = reader->readSampling();
332cb93a386Sopenharmony_ci            } else {
333cb93a386Sopenharmony_ci                sampling = SkSamplingOptions(SkFilterMode::kNearest);
334cb93a386Sopenharmony_ci            }
335cb93a386Sopenharmony_ci
336cb93a386Sopenharmony_ci            SkCanvas::SrcRectConstraint constraint =
337cb93a386Sopenharmony_ci                    reader->checkRange(SkCanvas::kStrict_SrcRectConstraint,
338cb93a386Sopenharmony_ci                                       SkCanvas::kFast_SrcRectConstraint);
339cb93a386Sopenharmony_ci
340cb93a386Sopenharmony_ci            if (!reader->validate(SkSafeMath::Mul(cnt, kEntryReadSize) <= reader->available())) {
341cb93a386Sopenharmony_ci                break;
342cb93a386Sopenharmony_ci            }
343cb93a386Sopenharmony_ci
344cb93a386Sopenharmony_ci            // Track minimum necessary clip points and matrices that must be provided to satisfy
345cb93a386Sopenharmony_ci            // the entries.
346cb93a386Sopenharmony_ci            int expectedClips = 0;
347cb93a386Sopenharmony_ci            int maxMatrixIndex = -1;
348cb93a386Sopenharmony_ci            SkAutoTArray<SkCanvas::ImageSetEntry> set(cnt);
349cb93a386Sopenharmony_ci            for (int i = 0; i < cnt && reader->isValid(); ++i) {
350cb93a386Sopenharmony_ci                set[i].fImage = sk_ref_sp(fPictureData->getImage(reader));
351cb93a386Sopenharmony_ci                reader->readRect(&set[i].fSrcRect);
352cb93a386Sopenharmony_ci                reader->readRect(&set[i].fDstRect);
353cb93a386Sopenharmony_ci                set[i].fMatrixIndex = reader->readInt();
354cb93a386Sopenharmony_ci                set[i].fAlpha = reader->readScalar();
355cb93a386Sopenharmony_ci                set[i].fAAFlags = reader->readUInt();
356cb93a386Sopenharmony_ci                set[i].fHasClip = reader->readInt();
357cb93a386Sopenharmony_ci
358cb93a386Sopenharmony_ci                expectedClips += set[i].fHasClip ? 1 : 0;
359cb93a386Sopenharmony_ci                if (set[i].fMatrixIndex > maxMatrixIndex) {
360cb93a386Sopenharmony_ci                    maxMatrixIndex = set[i].fMatrixIndex;
361cb93a386Sopenharmony_ci                }
362cb93a386Sopenharmony_ci            }
363cb93a386Sopenharmony_ci
364cb93a386Sopenharmony_ci            int dstClipCount = reader->readInt();
365cb93a386Sopenharmony_ci            SkPoint* dstClips = nullptr;
366cb93a386Sopenharmony_ci            if (!reader->validate(expectedClips <= dstClipCount)) {
367cb93a386Sopenharmony_ci                // Entries request more dstClip points than are provided in the buffer
368cb93a386Sopenharmony_ci                break;
369cb93a386Sopenharmony_ci            } else if (dstClipCount > 0) {
370cb93a386Sopenharmony_ci                dstClips = (SkPoint*) reader->skip(dstClipCount, sizeof(SkPoint));
371cb93a386Sopenharmony_ci                if (dstClips == nullptr) {
372cb93a386Sopenharmony_ci                    // Not enough bytes remaining so the reader has been invalidated
373cb93a386Sopenharmony_ci                    break;
374cb93a386Sopenharmony_ci                }
375cb93a386Sopenharmony_ci            }
376cb93a386Sopenharmony_ci            int matrixCount = reader->readInt();
377cb93a386Sopenharmony_ci            if (!reader->validate((maxMatrixIndex + 1) <= matrixCount) ||
378cb93a386Sopenharmony_ci                !reader->validate(
379cb93a386Sopenharmony_ci                    SkSafeMath::Mul(matrixCount, kMatrixSize) <= reader->available())) {
380cb93a386Sopenharmony_ci                // Entries access out-of-bound matrix indices, given provided matrices or
381cb93a386Sopenharmony_ci                // there aren't enough bytes to provide that many matrices
382cb93a386Sopenharmony_ci                break;
383cb93a386Sopenharmony_ci            }
384cb93a386Sopenharmony_ci            SkTArray<SkMatrix> matrices(matrixCount);
385cb93a386Sopenharmony_ci            for (int i = 0; i < matrixCount && reader->isValid(); ++i) {
386cb93a386Sopenharmony_ci                reader->readMatrix(&matrices.push_back());
387cb93a386Sopenharmony_ci            }
388cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
389cb93a386Sopenharmony_ci
390cb93a386Sopenharmony_ci            canvas->experimental_DrawEdgeAAImageSet(set.get(), cnt, dstClips, matrices.begin(),
391cb93a386Sopenharmony_ci                                                    sampling, paint, constraint);
392cb93a386Sopenharmony_ci        } break;
393cb93a386Sopenharmony_ci        case DRAW_IMAGE: {
394cb93a386Sopenharmony_ci            const SkPaint* paint = fPictureData->optionalPaint(reader);
395cb93a386Sopenharmony_ci            const SkImage* image = fPictureData->getImage(reader);
396cb93a386Sopenharmony_ci            SkPoint loc;
397cb93a386Sopenharmony_ci            reader->readPoint(&loc);
398cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
399cb93a386Sopenharmony_ci
400cb93a386Sopenharmony_ci            canvas->drawImage(image, loc.fX, loc.fY,
401cb93a386Sopenharmony_ci                              SkSamplingOptions(SkFilterMode::kNearest),
402cb93a386Sopenharmony_ci                              paint);
403cb93a386Sopenharmony_ci        } break;
404cb93a386Sopenharmony_ci        case DRAW_IMAGE2: {
405cb93a386Sopenharmony_ci            const SkPaint* paint = fPictureData->optionalPaint(reader);
406cb93a386Sopenharmony_ci            const SkImage* image = fPictureData->getImage(reader);
407cb93a386Sopenharmony_ci            SkPoint loc;
408cb93a386Sopenharmony_ci            reader->readPoint(&loc);
409cb93a386Sopenharmony_ci            SkSamplingOptions sampling = reader->readSampling();
410cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
411cb93a386Sopenharmony_ci
412cb93a386Sopenharmony_ci            canvas->drawImage(image, loc.fX, loc.fY, sampling, paint);
413cb93a386Sopenharmony_ci        } break;
414cb93a386Sopenharmony_ci        case DRAW_IMAGE_LATTICE: {
415cb93a386Sopenharmony_ci            const SkPaint* paint = fPictureData->optionalPaint(reader);
416cb93a386Sopenharmony_ci            const SkImage* image = fPictureData->getImage(reader);
417cb93a386Sopenharmony_ci            SkCanvas::Lattice lattice;
418cb93a386Sopenharmony_ci            (void)SkCanvasPriv::ReadLattice(*reader, &lattice);
419cb93a386Sopenharmony_ci            const SkRect* dst = reader->skipT<SkRect>();
420cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
421cb93a386Sopenharmony_ci
422cb93a386Sopenharmony_ci            canvas->drawImageLattice(image, lattice, *dst, SkFilterMode::kNearest, paint);
423cb93a386Sopenharmony_ci        } break;
424cb93a386Sopenharmony_ci        case DRAW_IMAGE_LATTICE2: {
425cb93a386Sopenharmony_ci            const SkPaint* paint = fPictureData->optionalPaint(reader);
426cb93a386Sopenharmony_ci            const SkImage* image = fPictureData->getImage(reader);
427cb93a386Sopenharmony_ci            SkCanvas::Lattice lattice;
428cb93a386Sopenharmony_ci            (void)SkCanvasPriv::ReadLattice(*reader, &lattice);
429cb93a386Sopenharmony_ci            const SkRect* dst = reader->skipT<SkRect>();
430cb93a386Sopenharmony_ci            SkFilterMode filter = reader->read32LE(SkFilterMode::kLinear);
431cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
432cb93a386Sopenharmony_ci
433cb93a386Sopenharmony_ci            canvas->drawImageLattice(image, lattice, *dst, filter, paint);
434cb93a386Sopenharmony_ci        } break;
435cb93a386Sopenharmony_ci        case DRAW_IMAGE_NINE: {
436cb93a386Sopenharmony_ci            const SkPaint* paint = fPictureData->optionalPaint(reader);
437cb93a386Sopenharmony_ci            const SkImage* image = fPictureData->getImage(reader);
438cb93a386Sopenharmony_ci            SkIRect center;
439cb93a386Sopenharmony_ci            reader->readIRect(&center);
440cb93a386Sopenharmony_ci            SkRect dst;
441cb93a386Sopenharmony_ci            reader->readRect(&dst);
442cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
443cb93a386Sopenharmony_ci
444cb93a386Sopenharmony_ci            canvas->drawImageNine(image, center, dst, SkFilterMode::kNearest, paint);
445cb93a386Sopenharmony_ci        } break;
446cb93a386Sopenharmony_ci        case DRAW_IMAGE_RECT: {
447cb93a386Sopenharmony_ci            const SkPaint* paint = fPictureData->optionalPaint(reader);
448cb93a386Sopenharmony_ci            const SkImage* image = fPictureData->getImage(reader);
449cb93a386Sopenharmony_ci            SkRect storage;
450cb93a386Sopenharmony_ci            const SkRect* src = get_rect_ptr(reader, &storage);   // may be null
451cb93a386Sopenharmony_ci            SkRect dst;
452cb93a386Sopenharmony_ci            reader->readRect(&dst);     // required
453cb93a386Sopenharmony_ci            // DRAW_IMAGE_RECT_STRICT assumes this constraint, and doesn't store it
454cb93a386Sopenharmony_ci            SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
455cb93a386Sopenharmony_ci            if (DRAW_IMAGE_RECT == op) {
456cb93a386Sopenharmony_ci                // newer op-code stores the constraint explicitly
457cb93a386Sopenharmony_ci                constraint = reader->checkRange(SkCanvas::kStrict_SrcRectConstraint,
458cb93a386Sopenharmony_ci                                                SkCanvas::kFast_SrcRectConstraint);
459cb93a386Sopenharmony_ci            }
460cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
461cb93a386Sopenharmony_ci
462cb93a386Sopenharmony_ci            auto sampling = SkSamplingOptions(SkFilterMode::kNearest);
463cb93a386Sopenharmony_ci            if (src) {
464cb93a386Sopenharmony_ci                canvas->drawImageRect(image, *src, dst, sampling, paint, constraint);
465cb93a386Sopenharmony_ci            } else {
466cb93a386Sopenharmony_ci                canvas->drawImageRect(image, dst, sampling, paint);
467cb93a386Sopenharmony_ci            }
468cb93a386Sopenharmony_ci        } break;
469cb93a386Sopenharmony_ci        case DRAW_IMAGE_RECT2: {
470cb93a386Sopenharmony_ci            const SkPaint* paint = fPictureData->optionalPaint(reader);
471cb93a386Sopenharmony_ci            const SkImage* image = fPictureData->getImage(reader);
472cb93a386Sopenharmony_ci            SkRect src = reader->readRect();
473cb93a386Sopenharmony_ci            SkRect dst = reader->readRect();
474cb93a386Sopenharmony_ci            SkSamplingOptions sampling = reader->readSampling();
475cb93a386Sopenharmony_ci            auto constraint = reader->read32LE(SkCanvas::kFast_SrcRectConstraint);
476cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
477cb93a386Sopenharmony_ci
478cb93a386Sopenharmony_ci            canvas->drawImageRect(image, src, dst, sampling, paint, constraint);
479cb93a386Sopenharmony_ci        } break;
480cb93a386Sopenharmony_ci        case DRAW_OVAL: {
481cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
482cb93a386Sopenharmony_ci            SkRect rect;
483cb93a386Sopenharmony_ci            reader->readRect(&rect);
484cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
485cb93a386Sopenharmony_ci
486cb93a386Sopenharmony_ci            canvas->drawOval(rect, paint);
487cb93a386Sopenharmony_ci        } break;
488cb93a386Sopenharmony_ci        case DRAW_PAINT: {
489cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
490cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
491cb93a386Sopenharmony_ci
492cb93a386Sopenharmony_ci            canvas->drawPaint(paint);
493cb93a386Sopenharmony_ci        } break;
494cb93a386Sopenharmony_ci        case DRAW_BEHIND_PAINT: {
495cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
496cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
497cb93a386Sopenharmony_ci
498cb93a386Sopenharmony_ci            SkCanvasPriv::DrawBehind(canvas, paint);
499cb93a386Sopenharmony_ci        } break;
500cb93a386Sopenharmony_ci        case DRAW_PATCH: {
501cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
502cb93a386Sopenharmony_ci
503cb93a386Sopenharmony_ci            const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts,
504cb93a386Sopenharmony_ci                                                                 sizeof(SkPoint));
505cb93a386Sopenharmony_ci            uint32_t flag = reader->readInt();
506cb93a386Sopenharmony_ci            const SkColor* colors = nullptr;
507cb93a386Sopenharmony_ci            if (flag & DRAW_VERTICES_HAS_COLORS) {
508cb93a386Sopenharmony_ci                colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners, sizeof(SkColor));
509cb93a386Sopenharmony_ci            }
510cb93a386Sopenharmony_ci            const SkPoint* texCoords = nullptr;
511cb93a386Sopenharmony_ci            if (flag & DRAW_VERTICES_HAS_TEXS) {
512cb93a386Sopenharmony_ci                texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners,
513cb93a386Sopenharmony_ci                                                         sizeof(SkPoint));
514cb93a386Sopenharmony_ci            }
515cb93a386Sopenharmony_ci            SkBlendMode bmode = SkBlendMode::kModulate;
516cb93a386Sopenharmony_ci            if (flag & DRAW_VERTICES_HAS_XFER) {
517cb93a386Sopenharmony_ci                unsigned mode = reader->readInt();
518cb93a386Sopenharmony_ci                if (mode <= (unsigned)SkBlendMode::kLastMode) {
519cb93a386Sopenharmony_ci                    bmode = (SkBlendMode)mode;
520cb93a386Sopenharmony_ci                }
521cb93a386Sopenharmony_ci            }
522cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
523cb93a386Sopenharmony_ci
524cb93a386Sopenharmony_ci            canvas->drawPatch(cubics, colors, texCoords, bmode, paint);
525cb93a386Sopenharmony_ci        } break;
526cb93a386Sopenharmony_ci        case DRAW_PATH: {
527cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
528cb93a386Sopenharmony_ci            const auto& path = fPictureData->getPath(reader);
529cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
530cb93a386Sopenharmony_ci
531cb93a386Sopenharmony_ci            canvas->drawPath(path, paint);
532cb93a386Sopenharmony_ci        } break;
533cb93a386Sopenharmony_ci        case DRAW_PICTURE: {
534cb93a386Sopenharmony_ci            const auto* pic = fPictureData->getPicture(reader);
535cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
536cb93a386Sopenharmony_ci
537cb93a386Sopenharmony_ci            canvas->drawPicture(pic);
538cb93a386Sopenharmony_ci        } break;
539cb93a386Sopenharmony_ci        case DRAW_PICTURE_MATRIX_PAINT: {
540cb93a386Sopenharmony_ci            const SkPaint* paint = fPictureData->optionalPaint(reader);
541cb93a386Sopenharmony_ci            SkMatrix matrix;
542cb93a386Sopenharmony_ci            reader->readMatrix(&matrix);
543cb93a386Sopenharmony_ci            const SkPicture* pic = fPictureData->getPicture(reader);
544cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
545cb93a386Sopenharmony_ci
546cb93a386Sopenharmony_ci            canvas->drawPicture(pic, &matrix, paint);
547cb93a386Sopenharmony_ci        } break;
548cb93a386Sopenharmony_ci        case DRAW_POINTS: {
549cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
550cb93a386Sopenharmony_ci            SkCanvas::PointMode mode = reader->checkRange(SkCanvas::kPoints_PointMode,
551cb93a386Sopenharmony_ci                                                          SkCanvas::kPolygon_PointMode);
552cb93a386Sopenharmony_ci            size_t count = reader->readInt();
553cb93a386Sopenharmony_ci            const SkPoint* pts = (const SkPoint*)reader->skip(count, sizeof(SkPoint));
554cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
555cb93a386Sopenharmony_ci
556cb93a386Sopenharmony_ci            canvas->drawPoints(mode, count, pts, paint);
557cb93a386Sopenharmony_ci        } break;
558cb93a386Sopenharmony_ci        case DRAW_RECT: {
559cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
560cb93a386Sopenharmony_ci            SkRect rect;
561cb93a386Sopenharmony_ci            reader->readRect(&rect);
562cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
563cb93a386Sopenharmony_ci
564cb93a386Sopenharmony_ci            canvas->drawRect(rect, paint);
565cb93a386Sopenharmony_ci        } break;
566cb93a386Sopenharmony_ci        case DRAW_REGION: {
567cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
568cb93a386Sopenharmony_ci            SkRegion region;
569cb93a386Sopenharmony_ci            reader->readRegion(&region);
570cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
571cb93a386Sopenharmony_ci
572cb93a386Sopenharmony_ci            canvas->drawRegion(region, paint);
573cb93a386Sopenharmony_ci        } break;
574cb93a386Sopenharmony_ci        case DRAW_RRECT: {
575cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
576cb93a386Sopenharmony_ci            SkRRect rrect;
577cb93a386Sopenharmony_ci            reader->readRRect(&rrect);
578cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
579cb93a386Sopenharmony_ci
580cb93a386Sopenharmony_ci            canvas->drawRRect(rrect, paint);
581cb93a386Sopenharmony_ci        } break;
582cb93a386Sopenharmony_ci        case DRAW_SHADOW_REC: {
583cb93a386Sopenharmony_ci            const auto& path = fPictureData->getPath(reader);
584cb93a386Sopenharmony_ci            SkDrawShadowRec rec;
585cb93a386Sopenharmony_ci            reader->readPoint3(&rec.fZPlaneParams);
586cb93a386Sopenharmony_ci            reader->readPoint3(&rec.fLightPos);
587cb93a386Sopenharmony_ci            rec.fLightRadius = reader->readScalar();
588cb93a386Sopenharmony_ci            rec.fAmbientColor = reader->read32();
589cb93a386Sopenharmony_ci            rec.fSpotColor = reader->read32();
590cb93a386Sopenharmony_ci            rec.fFlags = reader->read32();
591cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
592cb93a386Sopenharmony_ci
593cb93a386Sopenharmony_ci            canvas->private_draw_shadow_rec(path, rec);
594cb93a386Sopenharmony_ci        } break;
595cb93a386Sopenharmony_ci        case DRAW_TEXT_BLOB: {
596cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
597cb93a386Sopenharmony_ci            const SkTextBlob* blob = fPictureData->getTextBlob(reader);
598cb93a386Sopenharmony_ci            SkScalar x = reader->readScalar();
599cb93a386Sopenharmony_ci            SkScalar y = reader->readScalar();
600cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
601cb93a386Sopenharmony_ci
602cb93a386Sopenharmony_ci            canvas->drawTextBlob(blob, x, y, paint);
603cb93a386Sopenharmony_ci        } break;
604cb93a386Sopenharmony_ci        case DRAW_VERTICES_OBJECT: {
605cb93a386Sopenharmony_ci            const SkPaint& paint = fPictureData->requiredPaint(reader);
606cb93a386Sopenharmony_ci            const SkVertices* vertices = fPictureData->getVertices(reader);
607cb93a386Sopenharmony_ci            const int boneCount = reader->readInt();
608cb93a386Sopenharmony_ci            (void)reader->skip(boneCount, sizeof(SkVertices_DeprecatedBone));
609cb93a386Sopenharmony_ci            SkBlendMode bmode = reader->read32LE(SkBlendMode::kLastMode);
610cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
611cb93a386Sopenharmony_ci
612cb93a386Sopenharmony_ci            if (vertices) {  // TODO: read error if vertices == null?
613cb93a386Sopenharmony_ci                canvas->drawVertices(vertices, bmode, paint);
614cb93a386Sopenharmony_ci            }
615cb93a386Sopenharmony_ci        } break;
616cb93a386Sopenharmony_ci        case MARK_CTM: {
617cb93a386Sopenharmony_ci            SkString name;
618cb93a386Sopenharmony_ci            reader->readString(&name);
619cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
620cb93a386Sopenharmony_ci            canvas->markCTM(name.c_str());
621cb93a386Sopenharmony_ci        } break;
622cb93a386Sopenharmony_ci        case RESTORE:
623cb93a386Sopenharmony_ci            canvas->restore();
624cb93a386Sopenharmony_ci            break;
625cb93a386Sopenharmony_ci        case ROTATE: {
626cb93a386Sopenharmony_ci            auto deg = reader->readScalar();
627cb93a386Sopenharmony_ci            canvas->rotate(deg);
628cb93a386Sopenharmony_ci        } break;
629cb93a386Sopenharmony_ci        case SAVE:
630cb93a386Sopenharmony_ci            canvas->save();
631cb93a386Sopenharmony_ci            break;
632cb93a386Sopenharmony_ci        case SAVE_BEHIND: {
633cb93a386Sopenharmony_ci            uint32_t flags = reader->readInt();
634cb93a386Sopenharmony_ci            const SkRect* subset = nullptr;
635cb93a386Sopenharmony_ci            SkRect storage;
636cb93a386Sopenharmony_ci            if (flags & SAVEBEHIND_HAS_SUBSET) {
637cb93a386Sopenharmony_ci                reader->readRect(&storage);
638cb93a386Sopenharmony_ci                subset = &storage;
639cb93a386Sopenharmony_ci            }
640cb93a386Sopenharmony_ci            SkCanvasPriv::SaveBehind(canvas, subset);
641cb93a386Sopenharmony_ci        } break;
642cb93a386Sopenharmony_ci        case SAVE_LAYER_SAVELAYERREC: {
643cb93a386Sopenharmony_ci            SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, 0);
644cb93a386Sopenharmony_ci            const uint32_t flatFlags = reader->readInt();
645cb93a386Sopenharmony_ci            SkRect bounds;
646cb93a386Sopenharmony_ci            if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
647cb93a386Sopenharmony_ci                reader->readRect(&bounds);
648cb93a386Sopenharmony_ci                rec.fBounds = &bounds;
649cb93a386Sopenharmony_ci            }
650cb93a386Sopenharmony_ci            if (flatFlags & SAVELAYERREC_HAS_PAINT) {
651cb93a386Sopenharmony_ci                rec.fPaint = &fPictureData->requiredPaint(reader);
652cb93a386Sopenharmony_ci            }
653cb93a386Sopenharmony_ci            if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
654cb93a386Sopenharmony_ci                const SkPaint& paint = fPictureData->requiredPaint(reader);
655cb93a386Sopenharmony_ci                rec.fBackdrop = paint.getImageFilter();
656cb93a386Sopenharmony_ci            }
657cb93a386Sopenharmony_ci            if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
658cb93a386Sopenharmony_ci                rec.fSaveLayerFlags = reader->readInt();
659cb93a386Sopenharmony_ci            }
660cb93a386Sopenharmony_ci            if (flatFlags & SAVELAYERREC_HAS_CLIPMASK_OBSOLETE) {
661cb93a386Sopenharmony_ci                (void)fPictureData->getImage(reader);
662cb93a386Sopenharmony_ci            }
663cb93a386Sopenharmony_ci            if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX_OBSOLETE) {
664cb93a386Sopenharmony_ci                SkMatrix clipMatrix_ignored;
665cb93a386Sopenharmony_ci                reader->readMatrix(&clipMatrix_ignored);
666cb93a386Sopenharmony_ci            }
667cb93a386Sopenharmony_ci            if (!reader->isVersionLT(SkPicturePriv::Version::kBackdropScaleFactor) &&
668cb93a386Sopenharmony_ci                (flatFlags & SAVELAYERREC_HAS_BACKDROP_SCALE)) {
669cb93a386Sopenharmony_ci                SkCanvasPriv::SetBackdropScaleFactor(&rec, reader->readScalar());
670cb93a386Sopenharmony_ci            }
671cb93a386Sopenharmony_ci            BREAK_ON_READ_ERROR(reader);
672cb93a386Sopenharmony_ci
673cb93a386Sopenharmony_ci            canvas->saveLayer(rec);
674cb93a386Sopenharmony_ci        } break;
675cb93a386Sopenharmony_ci        case SCALE: {
676cb93a386Sopenharmony_ci            SkScalar sx = reader->readScalar();
677cb93a386Sopenharmony_ci            SkScalar sy = reader->readScalar();
678cb93a386Sopenharmony_ci            canvas->scale(sx, sy);
679cb93a386Sopenharmony_ci        } break;
680cb93a386Sopenharmony_ci        case SET_M44: {
681cb93a386Sopenharmony_ci            SkM44 m;
682cb93a386Sopenharmony_ci            reader->read(&m);
683cb93a386Sopenharmony_ci            canvas->setMatrix(initialMatrix * m);
684cb93a386Sopenharmony_ci        } break;
685cb93a386Sopenharmony_ci        case SET_MATRIX: {
686cb93a386Sopenharmony_ci            SkMatrix matrix;
687cb93a386Sopenharmony_ci            reader->readMatrix(&matrix);
688cb93a386Sopenharmony_ci            canvas->setMatrix(initialMatrix * SkM44(matrix));
689cb93a386Sopenharmony_ci        } break;
690cb93a386Sopenharmony_ci        case SKEW: {
691cb93a386Sopenharmony_ci            SkScalar sx = reader->readScalar();
692cb93a386Sopenharmony_ci            SkScalar sy = reader->readScalar();
693cb93a386Sopenharmony_ci            canvas->skew(sx, sy);
694cb93a386Sopenharmony_ci        } break;
695cb93a386Sopenharmony_ci        case TRANSLATE: {
696cb93a386Sopenharmony_ci            SkScalar dx = reader->readScalar();
697cb93a386Sopenharmony_ci            SkScalar dy = reader->readScalar();
698cb93a386Sopenharmony_ci            canvas->translate(dx, dy);
699cb93a386Sopenharmony_ci        } break;
700cb93a386Sopenharmony_ci        default:
701cb93a386Sopenharmony_ci            reader->validate(false);    // unknown op
702cb93a386Sopenharmony_ci            break;
703cb93a386Sopenharmony_ci    }
704cb93a386Sopenharmony_ci
705cb93a386Sopenharmony_ci#undef BREAK_ON_READ_ERROR
706cb93a386Sopenharmony_ci}
707