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 "SkFontPriv.h"
     12 #include "SkPaintPriv.h"
     13 #include "SkPatchUtils.h"
     14 #include "SkPictureData.h"
     15 #include "SkPicturePlayback.h"
     16 #include "SkPictureRecord.h"
     17 #include "SkReadBuffer.h"
     18 #include "SkRSXform.h"
     19 #include "SkSafeMath.h"
     20 #include "SkTextBlob.h"
     21 #include "SkTDArray.h"
     22 #include "SkTypes.h"
     23 
     24 // matches old SkCanvas::SaveFlags
     25 enum LegacySaveFlags {
     26     kClipToLayer_LegacySaveFlags      = 0x10,
     27 };
     28 
     29 SkCanvas::SaveLayerFlags SkCanvasPriv::LegacySaveFlagsToSaveLayerFlags(uint32_t flags) {
     30     uint32_t layerFlags = 0;
     31 
     32     if (0 == (flags & kClipToLayer_LegacySaveFlags)) {
     33         layerFlags |= kDontClipToLayer_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 ((temp & 0xFF) == 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 void SkPicturePlayback::draw(SkCanvas* canvas,
     72                              SkPicture::AbortCallback* callback,
     73                              SkReadBuffer* buffer) {
     74     AutoResetOpID aroi(this);
     75     SkASSERT(0 == fCurOffset);
     76 
     77     SkReadBuffer reader(fPictureData->opData()->bytes(),
     78                         fPictureData->opData()->size());
     79 
     80     // Record this, so we can concat w/ it if we encounter a setMatrix()
     81     SkMatrix initialMatrix = canvas->getTotalMatrix();
     82 
     83     SkAutoCanvasRestore acr(canvas, false);
     84 
     85     while (!reader.eof()) {
     86         if (callback && callback->abort()) {
     87             return;
     88         }
     89 
     90         fCurOffset = reader.offset();
     91         uint32_t size;
     92         DrawType op = ReadOpAndSize(&reader, &size);
     93         if (!reader.validate(op > UNUSED && op <= LAST_DRAWTYPE_ENUM)) {
     94             return;
     95         }
     96 
     97         this->handleOp(&reader, op, size, canvas, initialMatrix);
     98     }
     99 
    100     // need to propagate invalid state to the parent reader
    101     if (buffer) {
    102         buffer->validate(reader.isValid());
    103     }
    104 }
    105 
    106 static void validate_offsetToRestore(SkReadBuffer* reader, size_t offsetToRestore) {
    107     if (offsetToRestore) {
    108         reader->validate(SkIsAlign4(offsetToRestore) && offsetToRestore >= reader->offset());
    109     }
    110 }
    111 
    112 void SkPicturePlayback::handleOp(SkReadBuffer* reader,
    113                                  DrawType op,
    114                                  uint32_t size,
    115                                  SkCanvas* canvas,
    116                                  const SkMatrix& initialMatrix) {
    117 #define BREAK_ON_READ_ERROR(r) if (!r->isValid()) break
    118 
    119     switch (op) {
    120         case NOOP: {
    121             SkASSERT(size >= 4);
    122             reader->skip(size - 4);
    123         } break;
    124         case FLUSH:
    125             canvas->flush();
    126             break;
    127         case CLIP_PATH: {
    128             const SkPath& path = fPictureData->getPath(reader);
    129             uint32_t packed = reader->readInt();
    130             SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
    131             bool doAA = ClipParams_unpackDoAA(packed);
    132             size_t offsetToRestore = reader->readInt();
    133             validate_offsetToRestore(reader, offsetToRestore);
    134             BREAK_ON_READ_ERROR(reader);
    135 
    136             canvas->clipPath(path, clipOp, doAA);
    137             if (canvas->isClipEmpty() && offsetToRestore) {
    138                 reader->skip(offsetToRestore - reader->offset());
    139             }
    140         } break;
    141         case CLIP_REGION: {
    142             SkRegion region;
    143             reader->readRegion(&region);
    144             uint32_t packed = reader->readInt();
    145             SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
    146             size_t offsetToRestore = reader->readInt();
    147             validate_offsetToRestore(reader, offsetToRestore);
    148             BREAK_ON_READ_ERROR(reader);
    149 
    150             canvas->clipRegion(region, clipOp);
    151             if (canvas->isClipEmpty() && offsetToRestore) {
    152                 reader->skip(offsetToRestore - reader->offset());
    153             }
    154         } break;
    155         case CLIP_RECT: {
    156             SkRect rect;
    157             reader->readRect(&rect);
    158             uint32_t packed = reader->readInt();
    159             SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
    160             bool doAA = ClipParams_unpackDoAA(packed);
    161             size_t offsetToRestore = reader->readInt();
    162             validate_offsetToRestore(reader, offsetToRestore);
    163             BREAK_ON_READ_ERROR(reader);
    164 
    165             canvas->clipRect(rect, clipOp, doAA);
    166             if (canvas->isClipEmpty() && offsetToRestore) {
    167                 reader->skip(offsetToRestore - reader->offset());
    168             }
    169         } break;
    170         case CLIP_RRECT: {
    171             SkRRect rrect;
    172             reader->readRRect(&rrect);
    173             uint32_t packed = reader->readInt();
    174             SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
    175             bool doAA = ClipParams_unpackDoAA(packed);
    176             size_t offsetToRestore = reader->readInt();
    177             validate_offsetToRestore(reader, offsetToRestore);
    178             BREAK_ON_READ_ERROR(reader);
    179 
    180             canvas->clipRRect(rrect, clipOp, doAA);
    181             if (canvas->isClipEmpty() && offsetToRestore) {
    182                 reader->skip(offsetToRestore - reader->offset());
    183             }
    184         } break;
    185         case PUSH_CULL: break;  // Deprecated, safe to ignore both push and pop.
    186         case POP_CULL:  break;
    187         case CONCAT: {
    188             SkMatrix matrix;
    189             reader->readMatrix(&matrix);
    190             BREAK_ON_READ_ERROR(reader);
    191 
    192             canvas->concat(matrix);
    193             break;
    194         }
    195         case DRAW_ANNOTATION: {
    196             SkRect rect;
    197             reader->readRect(&rect);
    198             SkString key;
    199             reader->readString(&key);
    200             sk_sp<SkData> data = reader->readByteArrayAsData();
    201             BREAK_ON_READ_ERROR(reader);
    202             SkASSERT(data);
    203 
    204             canvas->drawAnnotation(rect, key.c_str(), data.get());
    205         } break;
    206         case DRAW_ARC: {
    207             const SkPaint* paint = fPictureData->getPaint(reader);
    208             SkRect rect;
    209             reader->readRect(&rect);
    210             SkScalar startAngle = reader->readScalar();
    211             SkScalar sweepAngle = reader->readScalar();
    212             int useCenter = reader->readInt();
    213             BREAK_ON_READ_ERROR(reader);
    214 
    215             if (paint) {
    216                 canvas->drawArc(rect, startAngle, sweepAngle, SkToBool(useCenter), *paint);
    217             }
    218         } break;
    219         case DRAW_ATLAS: {
    220             const SkPaint* paint = fPictureData->getPaint(reader);
    221             const SkImage* atlas = fPictureData->getImage(reader);
    222             const uint32_t flags = reader->readUInt();
    223             const int count = reader->readUInt();
    224             const SkRSXform* xform = (const SkRSXform*)reader->skip(count, sizeof(SkRSXform));
    225             const SkRect* tex = (const SkRect*)reader->skip(count, sizeof(SkRect));
    226             const SkColor* colors = nullptr;
    227             SkBlendMode mode = SkBlendMode::kDst;
    228             if (flags & DRAW_ATLAS_HAS_COLORS) {
    229                 colors = (const SkColor*)reader->skip(count, sizeof(SkColor));
    230                 mode = (SkBlendMode)reader->readUInt();
    231             }
    232             const SkRect* cull = nullptr;
    233             if (flags & DRAW_ATLAS_HAS_CULL) {
    234                 cull = (const SkRect*)reader->skip(sizeof(SkRect));
    235             }
    236             BREAK_ON_READ_ERROR(reader);
    237 
    238             canvas->drawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
    239         } break;
    240         case DRAW_CLEAR: {
    241             auto c = reader->readInt();
    242             BREAK_ON_READ_ERROR(reader);
    243 
    244             canvas->clear(c);
    245         } break;
    246         case DRAW_DATA: {
    247             // This opcode is now dead, just need to skip it for backwards compatibility
    248             size_t length = reader->readInt();
    249             (void)reader->skip(length);
    250             // skip handles padding the read out to a multiple of 4
    251         } break;
    252         case DRAW_DRAWABLE: {
    253             auto* d = fPictureData->getDrawable(reader);
    254             BREAK_ON_READ_ERROR(reader);
    255 
    256             canvas->drawDrawable(d);
    257         } break;
    258         case DRAW_DRAWABLE_MATRIX: {
    259             SkMatrix matrix;
    260             reader->readMatrix(&matrix);
    261             SkDrawable* drawable = fPictureData->getDrawable(reader);
    262             BREAK_ON_READ_ERROR(reader);
    263 
    264             canvas->drawDrawable(drawable, &matrix);
    265         } break;
    266         case DRAW_DRRECT: {
    267             const SkPaint* paint = fPictureData->getPaint(reader);
    268             SkRRect outer, inner;
    269             reader->readRRect(&outer);
    270             reader->readRRect(&inner);
    271             BREAK_ON_READ_ERROR(reader);
    272 
    273             if (paint) {
    274                 canvas->drawDRRect(outer, inner, *paint);
    275             }
    276         } break;
    277         case DRAW_EDGEAA_RECT: {
    278             SkRect rect;
    279             reader->readRect(&rect);
    280             SkCanvas::QuadAAFlags aaFlags = static_cast<SkCanvas::QuadAAFlags>(reader->read32());
    281             SkColor color = reader->read32();
    282             SkBlendMode blend = static_cast<SkBlendMode>(reader->read32());
    283             BREAK_ON_READ_ERROR(reader);
    284 
    285             canvas->experimental_DrawEdgeAARectV1(rect, aaFlags, color, blend);
    286         } break;
    287         case DRAW_IMAGE: {
    288             const SkPaint* paint = fPictureData->getPaint(reader);
    289             const SkImage* image = fPictureData->getImage(reader);
    290             SkPoint loc;
    291             reader->readPoint(&loc);
    292             BREAK_ON_READ_ERROR(reader);
    293 
    294             canvas->drawImage(image, loc.fX, loc.fY, paint);
    295         } break;
    296         case DRAW_IMAGE_LATTICE: {
    297             const SkPaint* paint = fPictureData->getPaint(reader);
    298             const SkImage* image = fPictureData->getImage(reader);
    299             SkCanvas::Lattice lattice;
    300             (void)SkCanvasPriv::ReadLattice(*reader, &lattice);
    301             const SkRect* dst = reader->skipT<SkRect>();
    302             BREAK_ON_READ_ERROR(reader);
    303 
    304             canvas->drawImageLattice(image, lattice, *dst, paint);
    305         } break;
    306         case DRAW_IMAGE_NINE: {
    307             const SkPaint* paint = fPictureData->getPaint(reader);
    308             const SkImage* image = fPictureData->getImage(reader);
    309             SkIRect center;
    310             reader->readIRect(&center);
    311             SkRect dst;
    312             reader->readRect(&dst);
    313             BREAK_ON_READ_ERROR(reader);
    314 
    315             canvas->drawImageNine(image, center, dst, paint);
    316         } break;
    317         case DRAW_IMAGE_RECT: {
    318             const SkPaint* paint = fPictureData->getPaint(reader);
    319             const SkImage* image = fPictureData->getImage(reader);
    320             SkRect storage;
    321             const SkRect* src = get_rect_ptr(reader, &storage);   // may be null
    322             SkRect dst;
    323             reader->readRect(&dst);     // required
    324             // DRAW_IMAGE_RECT_STRICT assumes this constraint, and doesn't store it
    325             SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
    326             if (DRAW_IMAGE_RECT == op) {
    327                 // newer op-code stores the constraint explicitly
    328                 constraint = (SkCanvas::SrcRectConstraint)reader->readInt();
    329             }
    330             BREAK_ON_READ_ERROR(reader);
    331 
    332             canvas->legacy_drawImageRect(image, src, dst, paint, constraint);
    333         } break;
    334         case DRAW_IMAGE_SET: {
    335             int cnt = reader->readInt();
    336             if (!reader->validate(cnt >= 0)) {
    337                 break;
    338             }
    339             SkFilterQuality filterQuality = (SkFilterQuality)reader->readUInt();
    340             SkBlendMode mode = (SkBlendMode)reader->readUInt();
    341             SkAutoTArray<SkCanvas::ImageSetEntry> set(cnt);
    342             for (int i = 0; i < cnt; ++i) {
    343                 set[i].fImage = sk_ref_sp(fPictureData->getImage(reader));
    344                 reader->readRect(&set[i].fSrcRect);
    345                 reader->readRect(&set[i].fDstRect);
    346                 set[i].fAlpha = reader->readScalar();
    347                 set[i].fAAFlags = reader->readUInt();
    348             }
    349             BREAK_ON_READ_ERROR(reader);
    350 
    351             canvas->experimental_DrawImageSetV1(set.get(), cnt, filterQuality, mode);
    352         } break;
    353         case DRAW_OVAL: {
    354             const SkPaint* paint = fPictureData->getPaint(reader);
    355             SkRect rect;
    356             reader->readRect(&rect);
    357             BREAK_ON_READ_ERROR(reader);
    358 
    359             if (paint) {
    360                 canvas->drawOval(rect, *paint);
    361             }
    362         } break;
    363         case DRAW_PAINT: {
    364             const SkPaint* paint = fPictureData->getPaint(reader);
    365             BREAK_ON_READ_ERROR(reader);
    366 
    367             if (paint) {
    368                 canvas->drawPaint(*paint);
    369             }
    370         } break;
    371         case DRAW_BEHIND_PAINT: {
    372             const SkPaint* paint = fPictureData->getPaint(reader);
    373             BREAK_ON_READ_ERROR(reader);
    374 
    375             if (paint) {
    376                 SkCanvasPriv::DrawBehind(canvas, *paint);
    377             }
    378         } break;
    379         case DRAW_PATCH: {
    380             const SkPaint* paint = fPictureData->getPaint(reader);
    381 
    382             const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts,
    383                                                                  sizeof(SkPoint));
    384             uint32_t flag = reader->readInt();
    385             const SkColor* colors = nullptr;
    386             if (flag & DRAW_VERTICES_HAS_COLORS) {
    387                 colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners, sizeof(SkColor));
    388             }
    389             const SkPoint* texCoords = nullptr;
    390             if (flag & DRAW_VERTICES_HAS_TEXS) {
    391                 texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners,
    392                                                          sizeof(SkPoint));
    393             }
    394             SkBlendMode bmode = SkBlendMode::kModulate;
    395             if (flag & DRAW_VERTICES_HAS_XFER) {
    396                 unsigned mode = reader->readInt();
    397                 if (mode <= (unsigned)SkBlendMode::kLastMode) {
    398                     bmode = (SkBlendMode)mode;
    399                 }
    400             }
    401             BREAK_ON_READ_ERROR(reader);
    402 
    403             if (paint) {
    404                 canvas->drawPatch(cubics, colors, texCoords, bmode, *paint);
    405             }
    406         } break;
    407         case DRAW_PATH: {
    408             const SkPaint* paint = fPictureData->getPaint(reader);
    409             const auto& path = fPictureData->getPath(reader);
    410             BREAK_ON_READ_ERROR(reader);
    411 
    412             if (paint) {
    413                 canvas->drawPath(path, *paint);
    414             }
    415         } break;
    416         case DRAW_PICTURE: {
    417             const auto* pic = fPictureData->getPicture(reader);
    418             BREAK_ON_READ_ERROR(reader);
    419 
    420             canvas->drawPicture(pic);
    421         } break;
    422         case DRAW_PICTURE_MATRIX_PAINT: {
    423             const SkPaint* paint = fPictureData->getPaint(reader);
    424             SkMatrix matrix;
    425             reader->readMatrix(&matrix);
    426             const SkPicture* pic = fPictureData->getPicture(reader);
    427             BREAK_ON_READ_ERROR(reader);
    428 
    429             canvas->drawPicture(pic, &matrix, paint);
    430         } break;
    431         case DRAW_POINTS: {
    432             const SkPaint* paint = fPictureData->getPaint(reader);
    433             SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt();
    434             size_t count = reader->readInt();
    435             const SkPoint* pts = (const SkPoint*)reader->skip(count, sizeof(SkPoint));
    436             BREAK_ON_READ_ERROR(reader);
    437 
    438             if (paint) {
    439                 canvas->drawPoints(mode, count, pts, *paint);
    440             }
    441         } break;
    442         case DRAW_RECT: {
    443             const SkPaint* paint = fPictureData->getPaint(reader);
    444             SkRect rect;
    445             reader->readRect(&rect);
    446             BREAK_ON_READ_ERROR(reader);
    447 
    448             if (paint) {
    449                 canvas->drawRect(rect, *paint);
    450             }
    451         } break;
    452         case DRAW_REGION: {
    453             const SkPaint* paint = fPictureData->getPaint(reader);
    454             SkRegion region;
    455             reader->readRegion(&region);
    456             BREAK_ON_READ_ERROR(reader);
    457 
    458             if (paint) {
    459                 canvas->drawRegion(region, *paint);
    460             }
    461         } break;
    462         case DRAW_RRECT: {
    463             const SkPaint* paint = fPictureData->getPaint(reader);
    464             SkRRect rrect;
    465             reader->readRRect(&rrect);
    466             BREAK_ON_READ_ERROR(reader);
    467 
    468             if (paint) {
    469                 canvas->drawRRect(rrect, *paint);
    470             }
    471         } break;
    472         case DRAW_SHADOW_REC: {
    473             const auto& path = fPictureData->getPath(reader);
    474             SkDrawShadowRec rec;
    475             reader->readPoint3(&rec.fZPlaneParams);
    476             reader->readPoint3(&rec.fLightPos);
    477             rec.fLightRadius = reader->readScalar();
    478             if (reader->isVersionLT(SkReadBuffer::kTwoColorDrawShadow_Version)) {
    479                 SkScalar ambientAlpha = reader->readScalar();
    480                 SkScalar spotAlpha = reader->readScalar();
    481                 SkColor color = reader->read32();
    482                 rec.fAmbientColor = SkColorSetA(color, SkColorGetA(color)*ambientAlpha);
    483                 rec.fSpotColor = SkColorSetA(color, SkColorGetA(color)*spotAlpha);
    484             } else {
    485                 rec.fAmbientColor = reader->read32();
    486                 rec.fSpotColor = reader->read32();
    487             }
    488             rec.fFlags = reader->read32();
    489             BREAK_ON_READ_ERROR(reader);
    490 
    491             canvas->private_draw_shadow_rec(path, rec);
    492         } break;
    493         case DRAW_TEXT_BLOB: {
    494             const SkPaint* paint = fPictureData->getPaint(reader);
    495             const SkTextBlob* blob = fPictureData->getTextBlob(reader);
    496             SkScalar x = reader->readScalar();
    497             SkScalar y = reader->readScalar();
    498             BREAK_ON_READ_ERROR(reader);
    499 
    500             if (paint) {
    501                 canvas->drawTextBlob(blob, x, y, *paint);
    502             }
    503         } break;
    504         case DRAW_VERTICES_OBJECT: {
    505             const SkPaint* paint = fPictureData->getPaint(reader);
    506             const SkVertices* vertices = fPictureData->getVertices(reader);
    507             const int boneCount = reader->readInt();
    508             const SkVertices::Bone* bones = boneCount ?
    509                     (const SkVertices::Bone*) reader->skip(boneCount, sizeof(SkVertices::Bone)) :
    510                     nullptr;
    511             SkBlendMode bmode = reader->read32LE(SkBlendMode::kLastMode);
    512             BREAK_ON_READ_ERROR(reader);
    513 
    514             if (paint && vertices) {
    515                 canvas->drawVertices(vertices, bones, boneCount, bmode, *paint);
    516             }
    517         } break;
    518         case RESTORE:
    519             canvas->restore();
    520             break;
    521         case ROTATE: {
    522             auto deg = reader->readScalar();
    523             canvas->rotate(deg);
    524         } break;
    525         case SAVE:
    526             canvas->save();
    527             break;
    528         case SAVE_BEHIND: {
    529             uint32_t flags = reader->readInt();
    530             const SkRect* subset = nullptr;
    531             SkRect storage;
    532             if (flags & SAVEBEHIND_HAS_SUBSET) {
    533                 reader->readRect(&storage);
    534                 subset = &storage;
    535             }
    536             SkCanvasPriv::SaveBehind(canvas, subset);
    537         } break;
    538         case SAVE_LAYER_SAVEFLAGS_DEPRECATED: {
    539             SkRect storage;
    540             const SkRect* boundsPtr = get_rect_ptr(reader, &storage);
    541             const SkPaint* paint = fPictureData->getPaint(reader);
    542             auto flags = SkCanvasPriv::LegacySaveFlagsToSaveLayerFlags(reader->readInt());
    543             BREAK_ON_READ_ERROR(reader);
    544 
    545             canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
    546         } break;
    547         case SAVE_LAYER_SAVELAYERREC: {
    548             SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, nullptr, nullptr, 0);
    549             SkMatrix clipMatrix;
    550             const uint32_t flatFlags = reader->readInt();
    551             SkRect bounds;
    552             if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
    553                 reader->readRect(&bounds);
    554                 rec.fBounds = &bounds;
    555             }
    556             if (flatFlags & SAVELAYERREC_HAS_PAINT) {
    557                 rec.fPaint = fPictureData->getPaint(reader);
    558             }
    559             if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
    560                 if (const auto* paint = fPictureData->getPaint(reader)) {
    561                     rec.fBackdrop = paint->getImageFilter();
    562                 }
    563             }
    564             if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
    565                 rec.fSaveLayerFlags = reader->readInt();
    566             }
    567             if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
    568                 rec.fClipMask = fPictureData->getImage(reader);
    569             }
    570             if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
    571                 reader->readMatrix(&clipMatrix);
    572                 rec.fClipMatrix = &clipMatrix;
    573             }
    574             BREAK_ON_READ_ERROR(reader);
    575 
    576             canvas->saveLayer(rec);
    577         } break;
    578         case SCALE: {
    579             SkScalar sx = reader->readScalar();
    580             SkScalar sy = reader->readScalar();
    581             canvas->scale(sx, sy);
    582         } break;
    583         case SET_MATRIX: {
    584             SkMatrix matrix;
    585             reader->readMatrix(&matrix);
    586             matrix.postConcat(initialMatrix);
    587             canvas->setMatrix(matrix);
    588         } break;
    589         case SKEW: {
    590             SkScalar sx = reader->readScalar();
    591             SkScalar sy = reader->readScalar();
    592             canvas->skew(sx, sy);
    593         } break;
    594         case TRANSLATE: {
    595             SkScalar dx = reader->readScalar();
    596             SkScalar dy = reader->readScalar();
    597             canvas->translate(dx, dy);
    598         } break;
    599         default:
    600             reader->validate(false);    // unknown op
    601             break;
    602     }
    603 
    604 #undef BREAK_ON_READ_ERROR
    605 }
    606