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 "SkCanvasPriv.h"
10 #include "SkDrawShadowInfo.h"
11 #include "SkPaintPriv.h"
12 #include "SkPatchUtils.h"
13 #include "SkPictureData.h"
14 #include "SkPicturePlayback.h"
15 #include "SkPictureRecord.h"
16 #include "SkReadBuffer.h"
17 #include "SkRSXform.h"
18 #include "SkSafeMath.h"
19 #include "SkTextBlob.h"
20 #include "SkTDArray.h"
21 #include "SkTypes.h"
22
23 // matches old SkCanvas::SaveFlags
24 enum LegacySaveFlags {
25 kClipToLayer_LegacySaveFlags = 0x10,
26 };
27
LegacySaveFlagsToSaveLayerFlags(uint32_t flags)28 SkCanvas::SaveLayerFlags SkCanvas::LegacySaveFlagsToSaveLayerFlags(uint32_t flags) {
29 uint32_t layerFlags = 0;
30
31 if (0 == (flags & kClipToLayer_LegacySaveFlags)) {
32 layerFlags |= SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag;
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:
TextContainer(SkReadBuffer * reader,const SkPaint * paint)72 TextContainer(SkReadBuffer* reader, const SkPaint* paint) {
73 if (reader->validate(paint != nullptr)) {
74 fByteLength = reader->readInt();
75 fText = (const char*)reader->skip(fByteLength);
76 if (reader->isValid()) {
77 if (fByteLength == 0) {
78 fCount = 0;
79 } else {
80 fCount = SkPaintPriv::ValidCountText(fText, fByteLength, paint->getTextEncoding());
81 reader->validate(fCount > 0);
82 }
83 }
84 }
85 }
86
operator bool() const87 MOZ_IMPLICIT operator bool() const { return fCount >= 0; }
88
length() const89 size_t length() const { return fByteLength; }
text() const90 const void* text() const { return (const void*)fText; }
count() const91 unsigned count() const { return fCount; }
92
93 private:
94 size_t fByteLength = 0;
95 const char* fText = nullptr;
96 int fCount = -1;
97 };
98
draw(SkCanvas * canvas,SkPicture::AbortCallback * callback,SkReadBuffer * buffer)99 void SkPicturePlayback::draw(SkCanvas* canvas,
100 SkPicture::AbortCallback* callback,
101 SkReadBuffer* buffer) {
102 AutoResetOpID aroi(this);
103 SkASSERT(0 == fCurOffset);
104
105 std::unique_ptr<SkReadBuffer> reader;
106 if (buffer) {
107 reader.reset(buffer->clone(fPictureData->opData()->bytes(),
108 fPictureData->opData()->size()));
109 } else {
110 reader.reset(new SkReadBuffer(fPictureData->opData()->bytes(),
111 fPictureData->opData()->size()));
112 }
113
114 // Record this, so we can concat w/ it if we encounter a setMatrix()
115 SkMatrix initialMatrix = canvas->getTotalMatrix();
116
117 SkAutoCanvasRestore acr(canvas, false);
118
119 while (!reader->eof()) {
120 if (callback && callback->abort()) {
121 return;
122 }
123
124 fCurOffset = reader->offset();
125 uint32_t size;
126 DrawType op = ReadOpAndSize(reader.get(), &size);
127 if (!reader->validate(op > UNUSED && op <= LAST_DRAWTYPE_ENUM)) {
128 return;
129 }
130
131 this->handleOp(reader.get(), op, size, canvas, initialMatrix);
132 }
133
134 // need to propagate invalid state to the parent reader
135 if (buffer) {
136 buffer->validate(reader->isValid());
137 }
138 }
139
validate_offsetToRestore(SkReadBuffer * reader,size_t offsetToRestore)140 static void validate_offsetToRestore(SkReadBuffer* reader, size_t offsetToRestore) {
141 if (offsetToRestore) {
142 reader->validate(SkIsAlign4(offsetToRestore) && offsetToRestore >= reader->offset());
143 }
144 }
145
handleOp(SkReadBuffer * reader,DrawType op,uint32_t size,SkCanvas * canvas,const SkMatrix & initialMatrix)146 void SkPicturePlayback::handleOp(SkReadBuffer* reader,
147 DrawType op,
148 uint32_t size,
149 SkCanvas* canvas,
150 const SkMatrix& initialMatrix) {
151 #define BREAK_ON_READ_ERROR(r) if (!r->isValid()) { break; }
152
153 switch (op) {
154 case NOOP: {
155 SkASSERT(size >= 4);
156 reader->skip(size - 4);
157 } break;
158 case FLUSH:
159 canvas->flush();
160 break;
161 case CLIP_PATH: {
162 const SkPath& path = fPictureData->getPath(reader);
163 uint32_t packed = reader->readInt();
164 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
165 bool doAA = ClipParams_unpackDoAA(packed);
166 size_t offsetToRestore = reader->readInt();
167 validate_offsetToRestore(reader, offsetToRestore);
168 BREAK_ON_READ_ERROR(reader);
169
170 canvas->clipPath(path, clipOp, doAA);
171 if (canvas->isClipEmpty() && offsetToRestore) {
172 reader->skip(offsetToRestore - reader->offset());
173 }
174 } break;
175 case CLIP_REGION: {
176 SkRegion region;
177 reader->readRegion(®ion);
178 uint32_t packed = reader->readInt();
179 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
180 size_t offsetToRestore = reader->readInt();
181 validate_offsetToRestore(reader, offsetToRestore);
182 BREAK_ON_READ_ERROR(reader);
183
184 canvas->clipRegion(region, clipOp);
185 if (canvas->isClipEmpty() && offsetToRestore) {
186 reader->skip(offsetToRestore - reader->offset());
187 }
188 } break;
189 case CLIP_RECT: {
190 SkRect rect;
191 reader->readRect(&rect);
192 uint32_t packed = reader->readInt();
193 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
194 bool doAA = ClipParams_unpackDoAA(packed);
195 size_t offsetToRestore = reader->readInt();
196 validate_offsetToRestore(reader, offsetToRestore);
197 BREAK_ON_READ_ERROR(reader);
198
199 canvas->clipRect(rect, clipOp, doAA);
200 if (canvas->isClipEmpty() && offsetToRestore) {
201 reader->skip(offsetToRestore - reader->offset());
202 }
203 } break;
204 case CLIP_RRECT: {
205 SkRRect rrect;
206 reader->readRRect(&rrect);
207 uint32_t packed = reader->readInt();
208 SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
209 bool doAA = ClipParams_unpackDoAA(packed);
210 size_t offsetToRestore = reader->readInt();
211 validate_offsetToRestore(reader, offsetToRestore);
212 BREAK_ON_READ_ERROR(reader);
213
214 canvas->clipRRect(rrect, clipOp, doAA);
215 if (canvas->isClipEmpty() && offsetToRestore) {
216 reader->skip(offsetToRestore - reader->offset());
217 }
218 } break;
219 case PUSH_CULL: break; // Deprecated, safe to ignore both push and pop.
220 case POP_CULL: break;
221 case CONCAT: {
222 SkMatrix matrix;
223 reader->readMatrix(&matrix);
224 BREAK_ON_READ_ERROR(reader);
225
226 canvas->concat(matrix);
227 break;
228 }
229 case DRAW_ANNOTATION: {
230 SkRect rect;
231 reader->readRect(&rect);
232 SkString key;
233 reader->readString(&key);
234 sk_sp<SkData> data = reader->readByteArrayAsData();
235 BREAK_ON_READ_ERROR(reader);
236
237 canvas->drawAnnotation(rect, key.c_str(), data.get());
238 } break;
239 case DRAW_ARC: {
240 const SkPaint* paint = fPictureData->getPaint(reader);
241 SkRect rect;
242 reader->readRect(&rect);
243 SkScalar startAngle = reader->readScalar();
244 SkScalar sweepAngle = reader->readScalar();
245 int useCenter = reader->readInt();
246 BREAK_ON_READ_ERROR(reader);
247
248 if (paint) {
249 canvas->drawArc(rect, startAngle, sweepAngle, SkToBool(useCenter), *paint);
250 }
251 } break;
252 case DRAW_ATLAS: {
253 const SkPaint* paint = fPictureData->getPaint(reader);
254 const SkImage* atlas = fPictureData->getImage(reader);
255 const uint32_t flags = reader->readUInt();
256 const int count = reader->readUInt();
257 const SkRSXform* xform = (const SkRSXform*)reader->skip(count, sizeof(SkRSXform));
258 const SkRect* tex = (const SkRect*)reader->skip(count, sizeof(SkRect));
259 const SkColor* colors = nullptr;
260 SkBlendMode mode = SkBlendMode::kDst;
261 if (flags & DRAW_ATLAS_HAS_COLORS) {
262 colors = (const SkColor*)reader->skip(count, sizeof(SkColor));
263 mode = (SkBlendMode)reader->readUInt();
264 }
265 const SkRect* cull = nullptr;
266 if (flags & DRAW_ATLAS_HAS_CULL) {
267 cull = (const SkRect*)reader->skip(sizeof(SkRect));
268 }
269 BREAK_ON_READ_ERROR(reader);
270
271 canvas->drawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
272 } break;
273 case DRAW_BITMAP: {
274 const SkPaint* paint = fPictureData->getPaint(reader);
275 const SkImage* image = fPictureData->getBitmapAsImage(reader);
276 SkPoint loc;
277 reader->readPoint(&loc);
278 BREAK_ON_READ_ERROR(reader);
279
280 canvas->drawImage(image, loc.fX, loc.fY, paint);
281 } break;
282 case DRAW_BITMAP_RECT: {
283 const SkPaint* paint = fPictureData->getPaint(reader);
284 const SkImage* image = fPictureData->getBitmapAsImage(reader);
285 SkRect storage;
286 const SkRect* src = get_rect_ptr(reader, &storage); // may be null
287 SkRect dst;
288 reader->readRect(&dst); // required
289 SkCanvas::SrcRectConstraint constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
290 BREAK_ON_READ_ERROR(reader);
291
292 if (src) {
293 canvas->drawImageRect(image, *src, dst, paint, constraint);
294 } else {
295 canvas->drawImageRect(image, dst, paint, constraint);
296 }
297 } break;
298 case DRAW_BITMAP_MATRIX: {
299 const SkPaint* paint = fPictureData->getPaint(reader);
300 const SkImage* image = fPictureData->getBitmapAsImage(reader);
301 SkMatrix matrix;
302 reader->readMatrix(&matrix);
303 BREAK_ON_READ_ERROR(reader);
304
305 SkAutoCanvasRestore acr(canvas, true);
306 canvas->concat(matrix);
307 canvas->drawImage(image, 0, 0, paint);
308 } break;
309 case DRAW_BITMAP_NINE: {
310 const SkPaint* paint = fPictureData->getPaint(reader);
311 const SkImage* image = fPictureData->getBitmapAsImage(reader);
312 SkIRect src;
313 reader->readIRect(&src);
314 SkRect dst;
315 reader->readRect(&dst);
316 BREAK_ON_READ_ERROR(reader);
317
318 canvas->drawImageNine(image, src, dst, paint);
319 } break;
320 case DRAW_CLEAR: {
321 auto c = reader->readInt();
322 BREAK_ON_READ_ERROR(reader);
323
324 canvas->clear(c);
325 } break;
326 case DRAW_DATA: {
327 // This opcode is now dead, just need to skip it for backwards compatibility
328 size_t length = reader->readInt();
329 (void)reader->skip(length);
330 // skip handles padding the read out to a multiple of 4
331 } break;
332 case DRAW_DRAWABLE: {
333 auto* d = fPictureData->getDrawable(reader);
334 BREAK_ON_READ_ERROR(reader);
335
336 canvas->drawDrawable(d);
337 } break;
338 case DRAW_DRAWABLE_MATRIX: {
339 SkMatrix matrix;
340 reader->readMatrix(&matrix);
341 SkDrawable* drawable = fPictureData->getDrawable(reader);
342 BREAK_ON_READ_ERROR(reader);
343
344 canvas->drawDrawable(drawable, &matrix);
345 } break;
346 case DRAW_DRRECT: {
347 const SkPaint* paint = fPictureData->getPaint(reader);
348 SkRRect outer, inner;
349 reader->readRRect(&outer);
350 reader->readRRect(&inner);
351 BREAK_ON_READ_ERROR(reader);
352
353 if (paint) {
354 canvas->drawDRRect(outer, inner, *paint);
355 }
356 } break;
357 case DRAW_IMAGE: {
358 const SkPaint* paint = fPictureData->getPaint(reader);
359 const SkImage* image = fPictureData->getImage(reader);
360 SkPoint loc;
361 reader->readPoint(&loc);
362 BREAK_ON_READ_ERROR(reader);
363
364 canvas->drawImage(image, loc.fX, loc.fY, paint);
365 } break;
366 case DRAW_IMAGE_LATTICE: {
367 const SkPaint* paint = fPictureData->getPaint(reader);
368 const SkImage* image = fPictureData->getImage(reader);
369 SkCanvas::Lattice lattice;
370 (void)SkCanvasPriv::ReadLattice(*reader, &lattice);
371 const SkRect* dst = reader->skipT<SkRect>();
372 BREAK_ON_READ_ERROR(reader);
373
374 canvas->drawImageLattice(image, lattice, *dst, paint);
375 } break;
376 case DRAW_IMAGE_NINE: {
377 const SkPaint* paint = fPictureData->getPaint(reader);
378 const SkImage* image = fPictureData->getImage(reader);
379 SkIRect center;
380 reader->readIRect(¢er);
381 SkRect dst;
382 reader->readRect(&dst);
383 BREAK_ON_READ_ERROR(reader);
384
385 canvas->drawImageNine(image, center, dst, paint);
386 } break;
387 case DRAW_IMAGE_RECT: {
388 const SkPaint* paint = fPictureData->getPaint(reader);
389 const SkImage* image = fPictureData->getImage(reader);
390 SkRect storage;
391 const SkRect* src = get_rect_ptr(reader, &storage); // may be null
392 SkRect dst;
393 reader->readRect(&dst); // required
394 // DRAW_IMAGE_RECT_STRICT assumes this constraint, and doesn't store it
395 SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
396 if (DRAW_IMAGE_RECT == op) {
397 // newer op-code stores the constraint explicitly
398 constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
399 }
400 BREAK_ON_READ_ERROR(reader);
401
402 canvas->legacy_drawImageRect(image, src, dst, paint, constraint);
403 } break;
404 case DRAW_OVAL: {
405 const SkPaint* paint = fPictureData->getPaint(reader);
406 SkRect rect;
407 reader->readRect(&rect);
408 BREAK_ON_READ_ERROR(reader);
409
410 if (paint) {
411 canvas->drawOval(rect, *paint);
412 }
413 } break;
414 case DRAW_PAINT: {
415 const SkPaint* paint = fPictureData->getPaint(reader);
416 BREAK_ON_READ_ERROR(reader);
417
418 if (paint) {
419 canvas->drawPaint(*paint);
420 }
421 } break;
422 case DRAW_PATCH: {
423 const SkPaint* paint = fPictureData->getPaint(reader);
424
425 const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts,
426 sizeof(SkPoint));
427 uint32_t flag = reader->readInt();
428 const SkColor* colors = nullptr;
429 if (flag & DRAW_VERTICES_HAS_COLORS) {
430 colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners, sizeof(SkColor));
431 }
432 const SkPoint* texCoords = nullptr;
433 if (flag & DRAW_VERTICES_HAS_TEXS) {
434 texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners,
435 sizeof(SkPoint));
436 }
437 SkBlendMode bmode = SkBlendMode::kModulate;
438 if (flag & DRAW_VERTICES_HAS_XFER) {
439 unsigned mode = reader->readInt();
440 if (mode <= (unsigned)SkBlendMode::kLastMode) {
441 bmode = (SkBlendMode)mode;
442 }
443 }
444 BREAK_ON_READ_ERROR(reader);
445
446 if (paint) {
447 canvas->drawPatch(cubics, colors, texCoords, bmode, *paint);
448 }
449 } break;
450 case DRAW_PATH: {
451 const SkPaint* paint = fPictureData->getPaint(reader);
452 const auto& path = fPictureData->getPath(reader);
453 BREAK_ON_READ_ERROR(reader);
454
455 if (paint) {
456 canvas->drawPath(path, *paint);
457 }
458 } break;
459 case DRAW_PICTURE: {
460 const auto* pic = fPictureData->getPicture(reader);
461 BREAK_ON_READ_ERROR(reader);
462
463 canvas->drawPicture(pic);
464 } break;
465 case DRAW_PICTURE_MATRIX_PAINT: {
466 const SkPaint* paint = fPictureData->getPaint(reader);
467 SkMatrix matrix;
468 reader->readMatrix(&matrix);
469 const SkPicture* pic = fPictureData->getPicture(reader);
470 BREAK_ON_READ_ERROR(reader);
471
472 canvas->drawPicture(pic, &matrix, paint);
473 } break;
474 case DRAW_POINTS: {
475 const SkPaint* paint = fPictureData->getPaint(reader);
476 SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt();
477 size_t count = reader->readInt();
478 const SkPoint* pts = (const SkPoint*)reader->skip(count, sizeof(SkPoint));
479 BREAK_ON_READ_ERROR(reader);
480
481 if (paint) {
482 canvas->drawPoints(mode, count, pts, *paint);
483 }
484 } break;
485 case DRAW_POS_TEXT: {
486 const SkPaint* paint = fPictureData->getPaint(reader);
487 TextContainer text(reader, paint);
488 size_t points = reader->readInt();
489 reader->validate(points == text.count());
490 const SkPoint* pos = (const SkPoint*)reader->skip(points, sizeof(SkPoint));
491 BREAK_ON_READ_ERROR(reader);
492
493 if (paint && text.text()) {
494 canvas->drawPosText(text.text(), text.length(), pos, *paint);
495 }
496 } break;
497 case DRAW_POS_TEXT_TOP_BOTTOM: {
498 const SkPaint* paint = fPictureData->getPaint(reader);
499 TextContainer text(reader, paint);
500 size_t points = reader->readInt();
501 reader->validate(points == text.count());
502 const SkPoint* pos = (const SkPoint*)reader->skip(points, sizeof(SkPoint));
503 const SkScalar top = reader->readScalar();
504 const SkScalar bottom = reader->readScalar();
505 BREAK_ON_READ_ERROR(reader);
506
507 SkRect clip = canvas->getLocalClipBounds();
508 if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
509 canvas->drawPosText(text.text(), text.length(), pos, *paint);
510 }
511 } break;
512 case DRAW_POS_TEXT_H: {
513 const SkPaint* paint = fPictureData->getPaint(reader);
514 TextContainer text(reader, paint);
515 size_t xCount = reader->readInt();
516 reader->validate(xCount == text.count());
517 const SkScalar constY = reader->readScalar();
518 const SkScalar* xpos = (const SkScalar*)reader->skip(xCount, sizeof(SkScalar));
519 BREAK_ON_READ_ERROR(reader);
520
521 if (paint && text.text()) {
522 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, *paint);
523 }
524 } break;
525 case DRAW_POS_TEXT_H_TOP_BOTTOM: {
526 const SkPaint* paint = fPictureData->getPaint(reader);
527 TextContainer text(reader, paint);
528 size_t xCount = reader->readInt();
529 reader->validate(xCount == text.count());
530 const SkScalar* xpos = (const SkScalar*)reader->skip(SkSafeMath::Add(3, xCount),
531 sizeof(SkScalar));
532 BREAK_ON_READ_ERROR(reader);
533
534 const SkScalar top = *xpos++;
535 const SkScalar bottom = *xpos++;
536 const SkScalar constY = *xpos++;
537 SkRect clip = canvas->getLocalClipBounds();
538 if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
539 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, *paint);
540 }
541 } break;
542 case DRAW_RECT: {
543 const SkPaint* paint = fPictureData->getPaint(reader);
544 SkRect rect;
545 reader->readRect(&rect);
546 BREAK_ON_READ_ERROR(reader);
547
548 if (paint) {
549 canvas->drawRect(rect, *paint);
550 }
551 } break;
552 case DRAW_REGION: {
553 const SkPaint* paint = fPictureData->getPaint(reader);
554 SkRegion region;
555 reader->readRegion(®ion);
556 BREAK_ON_READ_ERROR(reader);
557
558 if (paint) {
559 canvas->drawRegion(region, *paint);
560 }
561 } break;
562 case DRAW_RRECT: {
563 const SkPaint* paint = fPictureData->getPaint(reader);
564 SkRRect rrect;
565 reader->readRRect(&rrect);
566 BREAK_ON_READ_ERROR(reader);
567
568 if (paint) {
569 canvas->drawRRect(rrect, *paint);
570 }
571 } break;
572 case DRAW_SHADOW_REC: {
573 const auto& path = fPictureData->getPath(reader);
574 SkDrawShadowRec rec;
575 reader->readPoint3(&rec.fZPlaneParams);
576 reader->readPoint3(&rec.fLightPos);
577 rec.fLightRadius = reader->readScalar();
578 if (reader->isVersionLT(SkReadBuffer::kTwoColorDrawShadow_Version)) {
579 SkScalar ambientAlpha = reader->readScalar();
580 SkScalar spotAlpha = reader->readScalar();
581 SkColor color = reader->read32();
582 rec.fAmbientColor = SkColorSetA(color, SkColorGetA(color)*ambientAlpha);
583 rec.fSpotColor = SkColorSetA(color, SkColorGetA(color)*spotAlpha);
584 } else {
585 rec.fAmbientColor = reader->read32();
586 rec.fSpotColor = reader->read32();
587 }
588 rec.fFlags = reader->read32();
589 BREAK_ON_READ_ERROR(reader);
590
591 canvas->private_draw_shadow_rec(path, rec);
592 } break;
593 case DRAW_SPRITE: {
594 /* const SkPaint* paint = */ fPictureData->getPaint(reader);
595 /* const SkImage* image = */ fPictureData->getBitmapAsImage(reader);
596 /* int left = */ reader->readInt();
597 /* int top = */ reader->readInt();
598 // drawSprite removed dec-2015
599 } break;
600 case DRAW_TEXT: {
601 const SkPaint* paint = fPictureData->getPaint(reader);
602 TextContainer text(reader, paint);
603 SkScalar x = reader->readScalar();
604 SkScalar y = reader->readScalar();
605 BREAK_ON_READ_ERROR(reader);
606
607 if (paint && text.text()) {
608 canvas->drawText(text.text(), text.length(), x, y, *paint);
609 }
610 } break;
611 case DRAW_TEXT_BLOB: {
612 const SkPaint* paint = fPictureData->getPaint(reader);
613 const SkTextBlob* blob = fPictureData->getTextBlob(reader);
614 SkScalar x = reader->readScalar();
615 SkScalar y = reader->readScalar();
616 BREAK_ON_READ_ERROR(reader);
617
618 if (paint) {
619 canvas->drawTextBlob(blob, x, y, *paint);
620 }
621 } break;
622 case DRAW_TEXT_TOP_BOTTOM: {
623 const SkPaint* paint = fPictureData->getPaint(reader);
624 TextContainer text(reader, paint);
625 const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar));
626 BREAK_ON_READ_ERROR(reader);
627
628 // ptr[0] == x
629 // ptr[1] == y
630 // ptr[2] == top
631 // ptr[3] == bottom
632 SkRect clip = canvas->getLocalClipBounds();
633 float top = ptr[2];
634 float bottom = ptr[3];
635 if (top < clip.fBottom && bottom > clip.fTop && paint && text.text()) {
636 canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], *paint);
637 }
638 } break;
639 case DRAW_TEXT_ON_PATH: {
640 const SkPaint* paint = fPictureData->getPaint(reader);
641 TextContainer text(reader, paint);
642 const SkPath& path = fPictureData->getPath(reader);
643 SkMatrix matrix;
644 reader->readMatrix(&matrix);
645 BREAK_ON_READ_ERROR(reader);
646
647 if (paint && text.text()) {
648 canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, *paint);
649 }
650 } break;
651 case DRAW_TEXT_RSXFORM: {
652 const SkPaint* paint = fPictureData->getPaint(reader);
653 uint32_t count = reader->readUInt();
654 uint32_t flags = reader->readUInt();
655 TextContainer text(reader, paint);
656 const SkRSXform* xform = (const SkRSXform*)reader->skip(count, sizeof(SkRSXform));
657 const SkRect* cull = nullptr;
658 if (flags & DRAW_TEXT_RSXFORM_HAS_CULL) {
659 cull = (const SkRect*)reader->skip(sizeof(SkRect));
660 }
661 reader->validate(count == text.count());
662 BREAK_ON_READ_ERROR(reader);
663
664 if (text.text()) {
665 canvas->drawTextRSXform(text.text(), text.length(), xform, cull, *paint);
666 }
667 } break;
668 case DRAW_VERTICES_OBJECT: {
669 const SkPaint* paint = fPictureData->getPaint(reader);
670 const SkVertices* vertices = fPictureData->getVertices(reader);
671 SkBlendMode bmode = reader->read32LE(SkBlendMode::kLastMode);
672 BREAK_ON_READ_ERROR(reader);
673
674 if (paint && vertices) {
675 canvas->drawVertices(vertices, bmode, *paint);
676 }
677 } break;
678 case RESTORE:
679 canvas->restore();
680 break;
681 case ROTATE: {
682 auto deg = reader->readScalar();
683 canvas->rotate(deg);
684 } break;
685 case SAVE:
686 canvas->save();
687 break;
688 case SAVE_LAYER_SAVEFLAGS_DEPRECATED: {
689 SkRect storage;
690 const SkRect* boundsPtr = get_rect_ptr(reader, &storage);
691 const SkPaint* paint = fPictureData->getPaint(reader);
692 auto flags = SkCanvas::LegacySaveFlagsToSaveLayerFlags(reader->readInt());
693 BREAK_ON_READ_ERROR(reader);
694
695 canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
696 } break;
697 case SAVE_LAYER_SAVELAYERREC: {
698 SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, nullptr, nullptr, 0);
699 SkMatrix clipMatrix;
700 const uint32_t flatFlags = reader->readInt();
701 SkRect bounds;
702 if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
703 reader->readRect(&bounds);
704 rec.fBounds = &bounds;
705 }
706 if (flatFlags & SAVELAYERREC_HAS_PAINT) {
707 rec.fPaint = fPictureData->getPaint(reader);
708 }
709 if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
710 if (const auto* paint = fPictureData->getPaint(reader)) {
711 rec.fBackdrop = paint->getImageFilter();
712 }
713 }
714 if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
715 rec.fSaveLayerFlags = reader->readInt();
716 }
717 if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
718 rec.fClipMask = fPictureData->getImage(reader);
719 }
720 if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
721 reader->readMatrix(&clipMatrix);
722 rec.fClipMatrix = &clipMatrix;
723 }
724 BREAK_ON_READ_ERROR(reader);
725
726 canvas->saveLayer(rec);
727 } break;
728 case SCALE: {
729 SkScalar sx = reader->readScalar();
730 SkScalar sy = reader->readScalar();
731 canvas->scale(sx, sy);
732 } break;
733 case SET_MATRIX: {
734 SkMatrix matrix;
735 reader->readMatrix(&matrix);
736 matrix.postConcat(initialMatrix);
737 canvas->setMatrix(matrix);
738 } break;
739 case SKEW: {
740 SkScalar sx = reader->readScalar();
741 SkScalar sy = reader->readScalar();
742 canvas->skew(sx, sy);
743 } break;
744 case TRANSLATE: {
745 SkScalar dx = reader->readScalar();
746 SkScalar dy = reader->readScalar();
747 canvas->translate(dx, dy);
748 } break;
749 default:
750 reader->validate(false); // unknown op
751 break;
752 }
753
754 #undef BREAK_ON_READ_ERROR
755 }
756