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 SkColor4f color;
282 if (reader->isVersionLT(SkPicturePriv::kEdgeAAQuadColor4f_Version)) {
283 // Old version stored color as 8888
284 color = SkColor4f::FromColor(reader->read32());
285 } else {
286 reader->readColor4f(&color);
287 }
288 SkBlendMode blend = static_cast<SkBlendMode>(reader->read32());
289 bool hasClip = reader->readInt();
290 SkPoint* clip = nullptr;
291 if (hasClip) {
292 clip = (SkPoint*) reader->skip(4, sizeof(SkPoint));
293 }
294 BREAK_ON_READ_ERROR(reader);
295 canvas->experimental_DrawEdgeAAQuad(rect, clip, aaFlags, color, blend);
296 } break;
297 case DRAW_EDGEAA_IMAGE_SET: {
298 static const size_t kEntryReadSize =
299 4 * sizeof(uint32_t) + 2 * sizeof(SkRect) + sizeof(SkScalar);
300 static const size_t kMatrixSize = 9 * sizeof(SkScalar); // != sizeof(SkMatrix)
301
302 int cnt = reader->readInt();
303 if (!reader->validate(cnt >= 0)) {
304 break;
305 }
306 const SkPaint* paint = fPictureData->getPaint(reader);
307 SkCanvas::SrcRectConstraint constraint =
308 static_cast<SkCanvas::SrcRectConstraint>(reader->readInt());
309
310 if (!reader->validate(SkSafeMath::Mul(cnt, kEntryReadSize) <= reader->available())) {
311 break;
312 }
313
314 // Track minimum necessary clip points and matrices that must be provided to satisfy
315 // the entries.
316 int expectedClips = 0;
317 int maxMatrixIndex = -1;
318 SkAutoTArray<SkCanvas::ImageSetEntry> set(cnt);
319 for (int i = 0; i < cnt && reader->isValid(); ++i) {
320 set[i].fImage = sk_ref_sp(fPictureData->getImage(reader));
321 reader->readRect(&set[i].fSrcRect);
322 reader->readRect(&set[i].fDstRect);
323 set[i].fMatrixIndex = reader->readInt();
324 set[i].fAlpha = reader->readScalar();
325 set[i].fAAFlags = reader->readUInt();
326 set[i].fHasClip = reader->readInt();
327
328 expectedClips += set[i].fHasClip ? 1 : 0;
329 if (set[i].fMatrixIndex > maxMatrixIndex) {
330 maxMatrixIndex = set[i].fMatrixIndex;
331 }
332 }
333
334 int dstClipCount = reader->readInt();
335 SkPoint* dstClips = nullptr;
336 if (!reader->validate(expectedClips <= dstClipCount)) {
337 // Entries request more dstClip points than are provided in the buffer
338 break;
339 } else if (dstClipCount > 0) {
340 dstClips = (SkPoint*) reader->skip(dstClipCount, sizeof(SkPoint));
341 if (dstClips == nullptr) {
342 // Not enough bytes remaining so the reader has been invalidated
343 break;
344 }
345 }
346 int matrixCount = reader->readInt();
347 if (!reader->validate((maxMatrixIndex + 1) <= matrixCount) ||
348 !reader->validate(
349 SkSafeMath::Mul(matrixCount, kMatrixSize) <= reader->available())) {
350 // Entries access out-of-bound matrix indices, given provided matrices or
351 // there aren't enough bytes to provide that many matrices
352 break;
353 }
354 SkTArray<SkMatrix> matrices(matrixCount);
355 for (int i = 0; i < matrixCount && reader->isValid(); ++i) {
356 reader->readMatrix(&matrices.push_back());
357 }
358 BREAK_ON_READ_ERROR(reader);
359
360 canvas->experimental_DrawEdgeAAImageSet(set.get(), cnt, dstClips, matrices.begin(),
361 paint, constraint);
362 } break;
363 case DRAW_IMAGE: {
364 const SkPaint* paint = fPictureData->getPaint(reader);
365 const SkImage* image = fPictureData->getImage(reader);
366 SkPoint loc;
367 reader->readPoint(&loc);
368 BREAK_ON_READ_ERROR(reader);
369
370 canvas->drawImage(image, loc.fX, loc.fY, paint);
371 } break;
372 case DRAW_IMAGE_LATTICE: {
373 const SkPaint* paint = fPictureData->getPaint(reader);
374 const SkImage* image = fPictureData->getImage(reader);
375 SkCanvas::Lattice lattice;
376 (void)SkCanvasPriv::ReadLattice(*reader, &lattice);
377 const SkRect* dst = reader->skipT<SkRect>();
378 BREAK_ON_READ_ERROR(reader);
379
380 canvas->drawImageLattice(image, lattice, *dst, paint);
381 } break;
382 case DRAW_IMAGE_NINE: {
383 const SkPaint* paint = fPictureData->getPaint(reader);
384 const SkImage* image = fPictureData->getImage(reader);
385 SkIRect center;
386 reader->readIRect(¢er);
387 SkRect dst;
388 reader->readRect(&dst);
389 BREAK_ON_READ_ERROR(reader);
390
391 canvas->drawImageNine(image, center, dst, paint);
392 } break;
393 case DRAW_IMAGE_RECT: {
394 const SkPaint* paint = fPictureData->getPaint(reader);
395 const SkImage* image = fPictureData->getImage(reader);
396 SkRect storage;
397 const SkRect* src = get_rect_ptr(reader, &storage); // may be null
398 SkRect dst;
399 reader->readRect(&dst); // required
400 // DRAW_IMAGE_RECT_STRICT assumes this constraint, and doesn't store it
401 SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
402 if (DRAW_IMAGE_RECT == op) {
403 // newer op-code stores the constraint explicitly
404 constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
405 }
406 BREAK_ON_READ_ERROR(reader);
407
408 canvas->legacy_drawImageRect(image, src, dst, paint, constraint);
409 } break;
410 case DRAW_OVAL: {
411 const SkPaint* paint = fPictureData->getPaint(reader);
412 SkRect rect;
413 reader->readRect(&rect);
414 BREAK_ON_READ_ERROR(reader);
415
416 if (paint) {
417 canvas->drawOval(rect, *paint);
418 }
419 } break;
420 case DRAW_PAINT: {
421 const SkPaint* paint = fPictureData->getPaint(reader);
422 BREAK_ON_READ_ERROR(reader);
423
424 if (paint) {
425 canvas->drawPaint(*paint);
426 }
427 } break;
428 case DRAW_BEHIND_PAINT: {
429 const SkPaint* paint = fPictureData->getPaint(reader);
430 BREAK_ON_READ_ERROR(reader);
431
432 if (paint) {
433 SkCanvasPriv::DrawBehind(canvas, *paint);
434 }
435 } break;
436 case DRAW_PATCH: {
437 const SkPaint* paint = fPictureData->getPaint(reader);
438
439 const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts,
440 sizeof(SkPoint));
441 uint32_t flag = reader->readInt();
442 const SkColor* colors = nullptr;
443 if (flag & DRAW_VERTICES_HAS_COLORS) {
444 colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners, sizeof(SkColor));
445 }
446 const SkPoint* texCoords = nullptr;
447 if (flag & DRAW_VERTICES_HAS_TEXS) {
448 texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners,
449 sizeof(SkPoint));
450 }
451 SkBlendMode bmode = SkBlendMode::kModulate;
452 if (flag & DRAW_VERTICES_HAS_XFER) {
453 unsigned mode = reader->readInt();
454 if (mode <= (unsigned)SkBlendMode::kLastMode) {
455 bmode = (SkBlendMode)mode;
456 }
457 }
458 BREAK_ON_READ_ERROR(reader);
459
460 if (paint) {
461 canvas->drawPatch(cubics, colors, texCoords, bmode, *paint);
462 }
463 } break;
464 case DRAW_PATH: {
465 const SkPaint* paint = fPictureData->getPaint(reader);
466 const auto& path = fPictureData->getPath(reader);
467 BREAK_ON_READ_ERROR(reader);
468
469 if (paint) {
470 canvas->drawPath(path, *paint);
471 }
472 } break;
473 case DRAW_PICTURE: {
474 const auto* pic = fPictureData->getPicture(reader);
475 BREAK_ON_READ_ERROR(reader);
476
477 canvas->drawPicture(pic);
478 } break;
479 case DRAW_PICTURE_MATRIX_PAINT: {
480 const SkPaint* paint = fPictureData->getPaint(reader);
481 SkMatrix matrix;
482 reader->readMatrix(&matrix);
483 const SkPicture* pic = fPictureData->getPicture(reader);
484 BREAK_ON_READ_ERROR(reader);
485
486 canvas->drawPicture(pic, &matrix, paint);
487 } break;
488 case DRAW_POINTS: {
489 const SkPaint* paint = fPictureData->getPaint(reader);
490 SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt();
491 size_t count = reader->readInt();
492 const SkPoint* pts = (const SkPoint*)reader->skip(count, sizeof(SkPoint));
493 BREAK_ON_READ_ERROR(reader);
494
495 if (paint) {
496 canvas->drawPoints(mode, count, pts, *paint);
497 }
498 } break;
499 case DRAW_RECT: {
500 const SkPaint* paint = fPictureData->getPaint(reader);
501 SkRect rect;
502 reader->readRect(&rect);
503 BREAK_ON_READ_ERROR(reader);
504
505 if (paint) {
506 canvas->drawRect(rect, *paint);
507 }
508 } break;
509 case DRAW_REGION: {
510 const SkPaint* paint = fPictureData->getPaint(reader);
511 SkRegion region;
512 reader->readRegion(®ion);
513 BREAK_ON_READ_ERROR(reader);
514
515 if (paint) {
516 canvas->drawRegion(region, *paint);
517 }
518 } break;
519 case DRAW_RRECT: {
520 const SkPaint* paint = fPictureData->getPaint(reader);
521 SkRRect rrect;
522 reader->readRRect(&rrect);
523 BREAK_ON_READ_ERROR(reader);
524
525 if (paint) {
526 canvas->drawRRect(rrect, *paint);
527 }
528 } break;
529 case DRAW_SHADOW_REC: {
530 const auto& path = fPictureData->getPath(reader);
531 SkDrawShadowRec rec;
532 reader->readPoint3(&rec.fZPlaneParams);
533 reader->readPoint3(&rec.fLightPos);
534 rec.fLightRadius = reader->readScalar();
535 if (reader->isVersionLT(SkPicturePriv::kTwoColorDrawShadow_Version)) {
536 SkScalar ambientAlpha = reader->readScalar();
537 SkScalar spotAlpha = reader->readScalar();
538 SkColor color = reader->read32();
539 rec.fAmbientColor = SkColorSetA(color, SkColorGetA(color)*ambientAlpha);
540 rec.fSpotColor = SkColorSetA(color, SkColorGetA(color)*spotAlpha);
541 } else {
542 rec.fAmbientColor = reader->read32();
543 rec.fSpotColor = reader->read32();
544 }
545 rec.fFlags = reader->read32();
546 BREAK_ON_READ_ERROR(reader);
547
548 canvas->private_draw_shadow_rec(path, rec);
549 } break;
550 case DRAW_TEXT_BLOB: {
551 const SkPaint* paint = fPictureData->getPaint(reader);
552 const SkTextBlob* blob = fPictureData->getTextBlob(reader);
553 SkScalar x = reader->readScalar();
554 SkScalar y = reader->readScalar();
555 BREAK_ON_READ_ERROR(reader);
556
557 if (paint) {
558 canvas->drawTextBlob(blob, x, y, *paint);
559 }
560 } break;
561 case DRAW_VERTICES_OBJECT: {
562 const SkPaint* paint = fPictureData->getPaint(reader);
563 const SkVertices* vertices = fPictureData->getVertices(reader);
564 const int boneCount = reader->readInt();
565 const SkVertices::Bone* bones = boneCount ?
566 (const SkVertices::Bone*) reader->skip(boneCount, sizeof(SkVertices::Bone)) :
567 nullptr;
568 SkBlendMode bmode = reader->read32LE(SkBlendMode::kLastMode);
569 BREAK_ON_READ_ERROR(reader);
570
571 if (paint && vertices) {
572 canvas->drawVertices(vertices, bones, boneCount, bmode, *paint);
573 }
574 } break;
575 case RESTORE:
576 canvas->restore();
577 break;
578 case ROTATE: {
579 auto deg = reader->readScalar();
580 canvas->rotate(deg);
581 } break;
582 case SAVE:
583 canvas->save();
584 break;
585 case SAVE_BEHIND: {
586 uint32_t flags = reader->readInt();
587 const SkRect* subset = nullptr;
588 SkRect storage;
589 if (flags & SAVEBEHIND_HAS_SUBSET) {
590 reader->readRect(&storage);
591 subset = &storage;
592 }
593 SkCanvasPriv::SaveBehind(canvas, subset);
594 } break;
595 case SAVE_LAYER_SAVEFLAGS_DEPRECATED: {
596 SkRect storage;
597 const SkRect* boundsPtr = get_rect_ptr(reader, &storage);
598 const SkPaint* paint = fPictureData->getPaint(reader);
599 auto flags = SkCanvasPriv::LegacySaveFlagsToSaveLayerFlags(reader->readInt());
600 BREAK_ON_READ_ERROR(reader);
601
602 canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
603 } break;
604 case SAVE_LAYER_SAVELAYERREC: {
605 SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, nullptr, nullptr, 0);
606 SkMatrix clipMatrix;
607 const uint32_t flatFlags = reader->readInt();
608 SkRect bounds;
609 if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
610 reader->readRect(&bounds);
611 rec.fBounds = &bounds;
612 }
613 if (flatFlags & SAVELAYERREC_HAS_PAINT) {
614 rec.fPaint = fPictureData->getPaint(reader);
615 }
616 if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
617 if (const auto* paint = fPictureData->getPaint(reader)) {
618 rec.fBackdrop = paint->getImageFilter();
619 }
620 }
621 if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
622 rec.fSaveLayerFlags = reader->readInt();
623 }
624 if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
625 rec.fClipMask = fPictureData->getImage(reader);
626 }
627 if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
628 reader->readMatrix(&clipMatrix);
629 rec.fClipMatrix = &clipMatrix;
630 }
631 BREAK_ON_READ_ERROR(reader);
632
633 canvas->saveLayer(rec);
634 } break;
635 case SCALE: {
636 SkScalar sx = reader->readScalar();
637 SkScalar sy = reader->readScalar();
638 canvas->scale(sx, sy);
639 } break;
640 case SET_MATRIX: {
641 SkMatrix matrix;
642 reader->readMatrix(&matrix);
643 matrix.postConcat(initialMatrix);
644 canvas->setMatrix(matrix);
645 } break;
646 case SKEW: {
647 SkScalar sx = reader->readScalar();
648 SkScalar sy = reader->readScalar();
649 canvas->skew(sx, sy);
650 } break;
651 case TRANSLATE: {
652 SkScalar dx = reader->readScalar();
653 SkScalar dy = reader->readScalar();
654 canvas->translate(dx, dy);
655 } break;
656 default:
657 reader->validate(false); // unknown op
658 break;
659 }
660
661 #undef BREAK_ON_READ_ERROR
662 }
663