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     kClipToLayer_LegacySaveFlags      = 0x10,
     26 };
     27 
     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  */
     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 
     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:
     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 
     87     operator bool() const { return fCount >= 0; }
     88 
     89     size_t length() const { return fByteLength; }
     90     const void* text() const { return (const void*)fText; }
     91     unsigned count() const { return fCount; }
     92 
     93 private:
     94     size_t fByteLength = 0;
     95     const char* fText = nullptr;
     96     int fCount = -1;
     97 };
     98 
     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 
    140 static void validate_offsetToRestore(SkReadBuffer* reader, size_t offsetToRestore) {
    141     if (offsetToRestore) {
    142         reader->validate(SkIsAlign4(offsetToRestore) && offsetToRestore >= reader->offset());
    143     }
    144 }
    145 
    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(&region);
    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(&center);
    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(&region);
    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