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 "SkCanvas.h"
9 #include "SkPatchUtils.h"
10 #include "SkPictureData.h"
11 #include "SkPicturePlayback.h"
12 #include "SkPictureRecord.h"
13 #include "SkReadBuffer.h"
14 #include "SkRSXform.h"
15 #include "SkTextBlob.h"
16 #include "SkTDArray.h"
17 #include "SkTypes.h"
18
19 // matches old SkCanvas::SaveFlags
20 enum LegacySaveFlags {
21 kHasAlphaLayer_LegacySaveFlags = 0x04,
22 kClipToLayer_LegacySaveFlags = 0x10,
23 };
24
LegacySaveFlagsToSaveLayerFlags(uint32_t flags)25 SkCanvas::SaveLayerFlags SkCanvas::LegacySaveFlagsToSaveLayerFlags(uint32_t flags) {
26 uint32_t layerFlags = 0;
27
28 if (0 == (flags & kClipToLayer_LegacySaveFlags)) {
29 layerFlags |= SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag;
30 }
31 if (0 == (flags & kHasAlphaLayer_LegacySaveFlags)) {
32 layerFlags |= kIsOpaque_SaveLayerFlag;
33 }
34 return layerFlags;
35 }
36
37 /*
38 * Read the next op code and chunk size from 'reader'. The returned size
39 * is the entire size of the chunk (including the opcode). Thus, the
40 * offset just prior to calling ReadOpAndSize + 'size' is the offset
41 * to the next chunk's op code. This also means that the size of a chunk
42 * with no arguments (just an opcode) will be 4.
43 */
ReadOpAndSize(SkReadBuffer * reader,uint32_t * size)44 DrawType SkPicturePlayback::ReadOpAndSize(SkReadBuffer* reader, uint32_t* size) {
45 uint32_t temp = reader->readInt();
46 uint32_t op;
47 if (((uint8_t)temp) == temp) {
48 // old skp file - no size information
49 op = temp;
50 *size = 0;
51 } else {
52 UNPACK_8_24(temp, op, *size);
53 if (MASK_24 == *size) {
54 *size = reader->readInt();
55 }
56 }
57 return (DrawType)op;
58 }
59
60
get_rect_ptr(SkReadBuffer * reader,SkRect * storage)61 static const SkRect* get_rect_ptr(SkReadBuffer* reader, SkRect* storage) {
62 if (reader->readBool()) {
63 reader->readRect(storage);
64 return storage;
65 } else {
66 return nullptr;
67 }
68 }
69
70 class TextContainer {
71 public:
length()72 size_t length() { return fByteLength; }
text()73 const void* text() { return (const void*)fText; }
74 size_t fByteLength;
75 const char* fText;
76 };
77
get_text(SkReadBuffer * reader,TextContainer * text)78 void get_text(SkReadBuffer* reader, TextContainer* text) {
79 size_t length = text->fByteLength = reader->readInt();
80 text->fText = (const char*)reader->skip(length);
81 }
82
draw(SkCanvas * canvas,SkPicture::AbortCallback * callback,SkReadBuffer * buffer)83 void SkPicturePlayback::draw(SkCanvas* canvas,
84 SkPicture::AbortCallback* callback,
85 SkReadBuffer* buffer) {
86 AutoResetOpID aroi(this);
87 SkASSERT(0 == fCurOffset);
88
89 std::unique_ptr<SkReadBuffer> reader;
90 if (buffer) {
91 reader.reset(buffer->clone(fPictureData->opData()->bytes(),
92 fPictureData->opData()->size()));
93 } else {
94 reader.reset(new SkReadBuffer(fPictureData->opData()->bytes(),
95 fPictureData->opData()->size()));
96 }
97
98 // Record this, so we can concat w/ it if we encounter a setMatrix()
99 SkMatrix initialMatrix = canvas->getTotalMatrix();
100
101 SkAutoCanvasRestore acr(canvas, false);
102
103 while (!reader->eof()) {
104 if (callback && callback->abort()) {
105 return;
106 }
107
108 fCurOffset = reader->offset();
109 uint32_t size;
110 DrawType op = ReadOpAndSize(reader.get(), &size);
111 if (!reader->validate(op > UNUSED && op <= LAST_DRAWTYPE_ENUM)) {
112 return;
113 }
114
115 this->handleOp(reader.get(), op, size, canvas, initialMatrix);
116 }
117
118 // need to propagate invalid state to the parent reader
119 if (buffer) {
120 buffer->validate(reader->isValid());
121 }
122 }
123
handleOp(SkReadBuffer * reader,DrawType op,uint32_t size,SkCanvas * canvas,const SkMatrix & initialMatrix)124 void SkPicturePlayback::handleOp(SkReadBuffer* reader,
125 DrawType op,
126 uint32_t size,
127 SkCanvas* canvas,
128 const SkMatrix& initialMatrix) {
129 #define BREAK_ON_READ_ERROR(r) if (!r->isValid()) { break; }
130
131 switch (op) {
132 case NOOP: {
133 SkASSERT(size >= 4);
134 reader->skip(size - 4);
135 } break;
136 case CLIP_PATH: {
137 const SkPath& path = fPictureData->getPath(reader);
138 uint32_t packed = reader->readInt();
139 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
140 bool doAA = ClipParams_unpackDoAA(packed);
141 size_t offsetToRestore = reader->readInt();
142 BREAK_ON_READ_ERROR(reader);
143
144 SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
145 canvas->clipPath(path, clipOp, doAA);
146 if (canvas->isClipEmpty() && offsetToRestore) {
147 reader->skip(offsetToRestore - reader->offset());
148 }
149 } break;
150 case CLIP_REGION: {
151 SkRegion region;
152 reader->readRegion(®ion);
153 uint32_t packed = reader->readInt();
154 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
155 size_t offsetToRestore = reader->readInt();
156 BREAK_ON_READ_ERROR(reader);
157
158 SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
159 canvas->clipRegion(region, clipOp);
160 if (canvas->isClipEmpty() && offsetToRestore) {
161 reader->skip(offsetToRestore - reader->offset());
162 }
163 } break;
164 case CLIP_RECT: {
165 SkRect rect;
166 reader->readRect(&rect);
167 uint32_t packed = reader->readInt();
168 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
169 bool doAA = ClipParams_unpackDoAA(packed);
170 size_t offsetToRestore = reader->readInt();
171 BREAK_ON_READ_ERROR(reader);
172
173 SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
174 canvas->clipRect(rect, clipOp, doAA);
175 if (canvas->isClipEmpty() && offsetToRestore) {
176 reader->skip(offsetToRestore - reader->offset());
177 }
178 } break;
179 case CLIP_RRECT: {
180 SkRRect rrect;
181 reader->readRRect(&rrect);
182 uint32_t packed = reader->readInt();
183 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
184 bool doAA = ClipParams_unpackDoAA(packed);
185 size_t offsetToRestore = reader->readInt();
186 BREAK_ON_READ_ERROR(reader);
187
188 SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
189 canvas->clipRRect(rrect, clipOp, doAA);
190 if (canvas->isClipEmpty() && offsetToRestore) {
191 reader->skip(offsetToRestore - reader->offset());
192 }
193 } break;
194 case PUSH_CULL: break; // Deprecated, safe to ignore both push and pop.
195 case POP_CULL: break;
196 case CONCAT: {
197 SkMatrix matrix;
198 reader->readMatrix(&matrix);
199 BREAK_ON_READ_ERROR(reader);
200
201 canvas->concat(matrix);
202 break;
203 }
204 case DRAW_ANNOTATION: {
205 SkRect rect;
206 reader->readRect(&rect);
207 SkString key;
208 reader->readString(&key);
209 sk_sp<SkData> data = reader->readByteArrayAsData();
210 BREAK_ON_READ_ERROR(reader);
211
212 canvas->drawAnnotation(rect, key.c_str(), data.get());
213 } break;
214 case DRAW_ARC: {
215 const SkPaint* paint = fPictureData->getPaint(reader);
216 SkRect rect;
217 reader->readRect(&rect);
218 SkScalar startAngle = reader->readScalar();
219 SkScalar sweepAngle = reader->readScalar();
220 int useCenter = reader->readInt();
221 BREAK_ON_READ_ERROR(reader);
222
223 if (paint) {
224 canvas->drawArc(rect, startAngle, sweepAngle, SkToBool(useCenter), *paint);
225 }
226 } break;
227 case DRAW_ATLAS: {
228 const SkPaint* paint = fPictureData->getPaint(reader);
229 const SkImage* atlas = fPictureData->getImage(reader);
230 const uint32_t flags = reader->readUInt();
231 const int count = reader->readUInt();
232 const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform));
233 const SkRect* tex = (const SkRect*)reader->skip(count * sizeof(SkRect));
234 const SkColor* colors = nullptr;
235 SkBlendMode mode = SkBlendMode::kDst;
236 if (flags & DRAW_ATLAS_HAS_COLORS) {
237 colors = (const SkColor*)reader->skip(count * sizeof(SkColor));
238 mode = (SkBlendMode)reader->readUInt();
239 }
240 const SkRect* cull = nullptr;
241 if (flags & DRAW_ATLAS_HAS_CULL) {
242 cull = (const SkRect*)reader->skip(sizeof(SkRect));
243 }
244 BREAK_ON_READ_ERROR(reader);
245
246 canvas->drawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
247 } break;
248 case DRAW_BITMAP: {
249 const SkPaint* paint = fPictureData->getPaint(reader);
250 const SkImage* image = fPictureData->getBitmapAsImage(reader);
251 SkPoint loc;
252 reader->readPoint(&loc);
253 BREAK_ON_READ_ERROR(reader);
254
255 canvas->drawImage(image, loc.fX, loc.fY, paint);
256 } break;
257 case DRAW_BITMAP_RECT: {
258 const SkPaint* paint = fPictureData->getPaint(reader);
259 const SkImage* image = fPictureData->getBitmapAsImage(reader);
260 SkRect storage;
261 const SkRect* src = get_rect_ptr(reader, &storage); // may be null
262 SkRect dst;
263 reader->readRect(&dst); // required
264 SkCanvas::SrcRectConstraint constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
265 BREAK_ON_READ_ERROR(reader);
266
267 if (src) {
268 canvas->drawImageRect(image, *src, dst, paint, constraint);
269 } else {
270 canvas->drawImageRect(image, dst, paint, constraint);
271 }
272 } break;
273 case DRAW_BITMAP_MATRIX: {
274 const SkPaint* paint = fPictureData->getPaint(reader);
275 const SkImage* image = fPictureData->getBitmapAsImage(reader);
276 SkMatrix matrix;
277 reader->readMatrix(&matrix);
278 BREAK_ON_READ_ERROR(reader);
279
280 SkAutoCanvasRestore acr(canvas, true);
281 canvas->concat(matrix);
282 canvas->drawImage(image, 0, 0, paint);
283 } break;
284 case DRAW_BITMAP_NINE: {
285 const SkPaint* paint = fPictureData->getPaint(reader);
286 const SkImage* image = fPictureData->getBitmapAsImage(reader);
287 SkIRect src;
288 reader->readIRect(&src);
289 SkRect dst;
290 reader->readRect(&dst);
291 BREAK_ON_READ_ERROR(reader);
292
293 canvas->drawImageNine(image, src, dst, paint);
294 } break;
295 case DRAW_CLEAR: {
296 auto c = reader->readInt();
297 BREAK_ON_READ_ERROR(reader);
298
299 canvas->clear(c);
300 } break;
301 case DRAW_DATA: {
302 // This opcode is now dead, just need to skip it for backwards compatibility
303 size_t length = reader->readInt();
304 (void)reader->skip(length);
305 // skip handles padding the read out to a multiple of 4
306 } break;
307 case DRAW_DRAWABLE: {
308 auto* d = fPictureData->getDrawable(reader);
309 BREAK_ON_READ_ERROR(reader);
310
311 canvas->drawDrawable(d);
312 } break;
313 case DRAW_DRAWABLE_MATRIX: {
314 SkMatrix matrix;
315 reader->readMatrix(&matrix);
316 SkDrawable* drawable = fPictureData->getDrawable(reader);
317 BREAK_ON_READ_ERROR(reader);
318
319 canvas->drawDrawable(drawable, &matrix);
320 } break;
321 case DRAW_DRRECT: {
322 const SkPaint* paint = fPictureData->getPaint(reader);
323 SkRRect outer, inner;
324 reader->readRRect(&outer);
325 reader->readRRect(&inner);
326 BREAK_ON_READ_ERROR(reader);
327
328 if (paint) {
329 canvas->drawDRRect(outer, inner, *paint);
330 }
331 } break;
332 case BEGIN_COMMENT_GROUP: {
333 SkString tmp;
334 reader->readString(&tmp);
335 // deprecated (M44)
336 break;
337 }
338 case COMMENT: {
339 SkString tmp;
340 reader->readString(&tmp);
341 reader->readString(&tmp);
342 // deprecated (M44)
343 break;
344 }
345 case END_COMMENT_GROUP:
346 // deprecated (M44)
347 break;
348 case DRAW_IMAGE: {
349 const SkPaint* paint = fPictureData->getPaint(reader);
350 const SkImage* image = fPictureData->getImage(reader);
351 SkPoint loc;
352 reader->readPoint(&loc);
353 BREAK_ON_READ_ERROR(reader);
354
355 canvas->drawImage(image, loc.fX, loc.fY, paint);
356 } break;
357 case DRAW_IMAGE_LATTICE: {
358 const SkPaint* paint = fPictureData->getPaint(reader);
359 const SkImage* image = fPictureData->getImage(reader);
360 SkCanvas::Lattice lattice;
361 lattice.fXCount = reader->readInt();
362 lattice.fXDivs = (const int*) reader->skip(lattice.fXCount * sizeof(int32_t));
363 lattice.fYCount = reader->readInt();
364 lattice.fYDivs = (const int*) reader->skip(lattice.fYCount * sizeof(int32_t));
365 int flagCount = reader->readInt();
366 lattice.fFlags = (0 == flagCount) ? nullptr : (const SkCanvas::Lattice::Flags*)
367 reader->skip(SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags)));
368 SkIRect src;
369 reader->readIRect(&src);
370 lattice.fBounds = &src;
371 SkRect dst;
372 reader->readRect(&dst);
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(¢er);
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_STRICT:
389 case DRAW_IMAGE_RECT: {
390 const SkPaint* paint = fPictureData->getPaint(reader);
391 const SkImage* image = fPictureData->getImage(reader);
392 SkRect storage;
393 const SkRect* src = get_rect_ptr(reader, &storage); // may be null
394 SkRect dst;
395 reader->readRect(&dst); // required
396 // DRAW_IMAGE_RECT_STRICT assumes this constraint, and doesn't store it
397 SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
398 if (DRAW_IMAGE_RECT == op) {
399 // newer op-code stores the constraint explicitly
400 constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
401 }
402 BREAK_ON_READ_ERROR(reader);
403
404 canvas->legacy_drawImageRect(image, src, dst, paint, constraint);
405 } break;
406 case DRAW_OVAL: {
407 const SkPaint* paint = fPictureData->getPaint(reader);
408 SkRect rect;
409 reader->readRect(&rect);
410 BREAK_ON_READ_ERROR(reader);
411
412 if (paint) {
413 canvas->drawOval(rect, *paint);
414 }
415 } break;
416 case DRAW_PAINT: {
417 const SkPaint* paint = fPictureData->getPaint(reader);
418 BREAK_ON_READ_ERROR(reader);
419
420 if (paint) {
421 canvas->drawPaint(*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(sizeof(SkPoint)* count);
481 BREAK_ON_READ_ERROR(reader);
482
483 if (paint) {
484 canvas->drawPoints(mode, count, pts, *paint);
485 }
486 } break;
487 case DRAW_POS_TEXT: {
488 const SkPaint* paint = fPictureData->getPaint(reader);
489 TextContainer text;
490 get_text(reader, &text);
491 size_t points = reader->readInt();
492 const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
493 BREAK_ON_READ_ERROR(reader);
494
495 if (paint && text.text()) {
496 canvas->drawPosText(text.text(), text.length(), pos, *paint);
497 }
498 } break;
499 case DRAW_POS_TEXT_TOP_BOTTOM: {
500 const SkPaint* paint = fPictureData->getPaint(reader);
501 TextContainer text;
502 get_text(reader, &text);
503 size_t points = reader->readInt();
504 const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
505 const SkScalar top = reader->readScalar();
506 const SkScalar bottom = reader->readScalar();
507 BREAK_ON_READ_ERROR(reader);
508
509 SkRect clip = canvas->getLocalClipBounds();
510 if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
511 canvas->drawPosText(text.text(), text.length(), pos, *paint);
512 }
513 } break;
514 case DRAW_POS_TEXT_H: {
515 const SkPaint* paint = fPictureData->getPaint(reader);
516 TextContainer text;
517 get_text(reader, &text);
518 size_t xCount = reader->readInt();
519 const SkScalar constY = reader->readScalar();
520 const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar));
521 BREAK_ON_READ_ERROR(reader);
522
523 if (paint && text.text()) {
524 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, *paint);
525 }
526 } break;
527 case DRAW_POS_TEXT_H_TOP_BOTTOM: {
528 const SkPaint* paint = fPictureData->getPaint(reader);
529 TextContainer text;
530 get_text(reader, &text);
531 size_t xCount = reader->readInt();
532 const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar));
533 BREAK_ON_READ_ERROR(reader);
534
535 const SkScalar top = *xpos++;
536 const SkScalar bottom = *xpos++;
537 const SkScalar constY = *xpos++;
538 SkRect clip = canvas->getLocalClipBounds();
539 if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
540 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, *paint);
541 }
542 } break;
543 case DRAW_RECT: {
544 const SkPaint* paint = fPictureData->getPaint(reader);
545 SkRect rect;
546 reader->readRect(&rect);
547 BREAK_ON_READ_ERROR(reader);
548
549 if (paint) {
550 canvas->drawRect(rect, *paint);
551 }
552 } break;
553 case DRAW_REGION: {
554 const SkPaint* paint = fPictureData->getPaint(reader);
555 SkRegion region;
556 reader->readRegion(®ion);
557 BREAK_ON_READ_ERROR(reader);
558
559 if (paint) {
560 canvas->drawRegion(region, *paint);
561 }
562 } break;
563 case DRAW_RRECT: {
564 const SkPaint* paint = fPictureData->getPaint(reader);
565 SkRRect rrect;
566 reader->readRRect(&rrect);
567 BREAK_ON_READ_ERROR(reader);
568
569 if (paint) {
570 canvas->drawRRect(rrect, *paint);
571 }
572 } break;
573 case DRAW_SPRITE: {
574 /* const SkPaint* paint = */ fPictureData->getPaint(reader);
575 /* const SkImage* image = */ fPictureData->getBitmapAsImage(reader);
576 /* int left = */ reader->readInt();
577 /* int top = */ reader->readInt();
578 // drawSprite removed dec-2015
579 } break;
580 case DRAW_TEXT: {
581 const SkPaint* paint = fPictureData->getPaint(reader);
582 TextContainer text;
583 get_text(reader, &text);
584 SkScalar x = reader->readScalar();
585 SkScalar y = reader->readScalar();
586 BREAK_ON_READ_ERROR(reader);
587
588 if (paint && text.text()) {
589 canvas->drawText(text.text(), text.length(), x, y, *paint);
590 }
591 } break;
592 case DRAW_TEXT_BLOB: {
593 const SkPaint* paint = fPictureData->getPaint(reader);
594 const SkTextBlob* blob = fPictureData->getTextBlob(reader);
595 SkScalar x = reader->readScalar();
596 SkScalar y = reader->readScalar();
597 BREAK_ON_READ_ERROR(reader);
598
599 if (paint) {
600 canvas->drawTextBlob(blob, x, y, *paint);
601 }
602 } break;
603 case DRAW_TEXT_TOP_BOTTOM: {
604 const SkPaint* paint = fPictureData->getPaint(reader);
605 TextContainer text;
606 get_text(reader, &text);
607 const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar));
608 BREAK_ON_READ_ERROR(reader);
609
610 // ptr[0] == x
611 // ptr[1] == y
612 // ptr[2] == top
613 // ptr[3] == bottom
614 SkRect clip = canvas->getLocalClipBounds();
615 float top = ptr[2];
616 float bottom = ptr[3];
617 if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
618 canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], *paint);
619 }
620 } break;
621 case DRAW_TEXT_ON_PATH: {
622 const SkPaint* paint = fPictureData->getPaint(reader);
623 TextContainer text;
624 get_text(reader, &text);
625 const SkPath& path = fPictureData->getPath(reader);
626 SkMatrix matrix;
627 reader->readMatrix(&matrix);
628 BREAK_ON_READ_ERROR(reader);
629
630 if (paint && text.text()) {
631 canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, *paint);
632 }
633 } break;
634 case DRAW_TEXT_RSXFORM: {
635 const SkPaint* paint = fPictureData->getPaint(reader);
636 int count = reader->readInt();
637 uint32_t flags = reader->read32();
638 TextContainer text;
639 get_text(reader, &text);
640 const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform));
641 const SkRect* cull = nullptr;
642 if (flags & DRAW_TEXT_RSXFORM_HAS_CULL) {
643 cull = (const SkRect*)reader->skip(sizeof(SkRect));
644 }
645 BREAK_ON_READ_ERROR(reader);
646
647 if (text.text()) {
648 canvas->drawTextRSXform(text.text(), text.length(), xform, cull, *paint);
649 }
650 } break;
651 case DRAW_VERTICES_RETIRED_03_2017: {
652 const SkPaint* paint = fPictureData->getPaint(reader);
653 DrawVertexFlags flags = (DrawVertexFlags)reader->readInt();
654 SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt();
655 int vCount = reader->readInt();
656 const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
657 const SkPoint* texs = nullptr;
658 const SkColor* colors = nullptr;
659 const uint16_t* indices = nullptr;
660 int iCount = 0;
661 if (flags & DRAW_VERTICES_HAS_TEXS) {
662 texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
663 }
664 if (flags & DRAW_VERTICES_HAS_COLORS) {
665 colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor));
666 }
667 if (flags & DRAW_VERTICES_HAS_INDICES) {
668 iCount = reader->readInt();
669 indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t));
670 }
671 SkBlendMode bmode = SkBlendMode::kModulate;
672 if (flags & DRAW_VERTICES_HAS_XFER) {
673 unsigned mode = reader->readInt();
674 if (mode <= (unsigned)SkBlendMode::kLastMode) {
675 bmode = (SkBlendMode)mode;
676 }
677 }
678 BREAK_ON_READ_ERROR(reader);
679
680 if (paint) {
681 canvas->drawVertices(SkVertices::MakeCopy(vmode, vCount, verts, texs, colors,
682 iCount, indices), bmode, *paint);
683 }
684 } break;
685 case DRAW_VERTICES_OBJECT: {
686 const SkPaint* paint = fPictureData->getPaint(reader);
687 const SkVertices* vertices = fPictureData->getVertices(reader);
688 SkBlendMode bmode = static_cast<SkBlendMode>(reader->readInt());
689
690 BREAK_ON_READ_ERROR(reader);
691
692 if (paint && vertices) {
693 canvas->drawVertices(vertices, bmode, *paint);
694 }
695 } break;
696 case RESTORE:
697 canvas->restore();
698 break;
699 case ROTATE: {
700 auto deg = reader->readScalar();
701 BREAK_ON_READ_ERROR(reader);
702
703 canvas->rotate(deg);
704 } break;
705 case SAVE:
706 canvas->save();
707 break;
708 case SAVE_LAYER_SAVEFLAGS_DEPRECATED: {
709 SkRect storage;
710 const SkRect* boundsPtr = get_rect_ptr(reader, &storage);
711 const SkPaint* paint = fPictureData->getPaint(reader);
712 auto flags = SkCanvas::LegacySaveFlagsToSaveLayerFlags(reader->readInt());
713 BREAK_ON_READ_ERROR(reader);
714
715 canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
716 } break;
717 case SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016: {
718 SkRect storage;
719 const SkRect* boundsPtr = get_rect_ptr(reader, &storage);
720 const SkPaint* paint = fPictureData->getPaint(reader);
721 auto flags = reader->readInt();
722 BREAK_ON_READ_ERROR(reader);
723
724 canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
725 } break;
726 case SAVE_LAYER_SAVELAYERREC: {
727 SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, 0);
728 const uint32_t flatFlags = reader->readInt();
729 SkRect bounds;
730 if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
731 reader->readRect(&bounds);
732 rec.fBounds = &bounds;
733 }
734 if (flatFlags & SAVELAYERREC_HAS_PAINT) {
735 rec.fPaint = fPictureData->getPaint(reader);
736 }
737 if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
738 if (const auto* paint = fPictureData->getPaint(reader)) {
739 rec.fBackdrop = paint->getImageFilter();
740 }
741 }
742 if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
743 rec.fSaveLayerFlags = reader->readInt();
744 }
745 BREAK_ON_READ_ERROR(reader);
746
747 canvas->saveLayer(rec);
748 } break;
749 case SCALE: {
750 SkScalar sx = reader->readScalar();
751 SkScalar sy = reader->readScalar();
752 BREAK_ON_READ_ERROR(reader);
753
754 canvas->scale(sx, sy);
755 } break;
756 case SET_MATRIX: {
757 SkMatrix matrix;
758 reader->readMatrix(&matrix);
759 BREAK_ON_READ_ERROR(reader);
760
761 matrix.postConcat(initialMatrix);
762 canvas->setMatrix(matrix);
763 } break;
764 case SKEW: {
765 SkScalar sx = reader->readScalar();
766 SkScalar sy = reader->readScalar();
767 BREAK_ON_READ_ERROR(reader);
768
769 canvas->skew(sx, sy);
770 } break;
771 case TRANSLATE: {
772 SkScalar dx = reader->readScalar();
773 SkScalar dy = reader->readScalar();
774 BREAK_ON_READ_ERROR(reader);
775
776 canvas->translate(dx, dy);
777 } break;
778 case TRANSLATE_Z: {
779 #ifdef SK_EXPERIMENTAL_SHADOWING
780 SkScalar dz = reader->readScalar();
781 BREAK_ON_READ_ERROR(reader);
782
783 canvas->translateZ(dz);
784 #endif
785 } break;
786 default:
787 SkASSERTF(false, "Unknown draw type: %d", op);
788 }
789
790 #undef BREAK_ON_READ_ERROR
791 }
792