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