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