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