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