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