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