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 "SkPatchUtils.h"
     10 #include "SkPictureData.h"
     11 #include "SkPicturePlayback.h"
     12 #include "SkPictureRecord.h"
     13 #include "SkReader32.h"
     14 #include "SkTextBlob.h"
     15 #include "SkTDArray.h"
     16 #include "SkTypes.h"
     17 
     18 /*
     19  * Read the next op code and chunk size from 'reader'. The returned size
     20  * is the entire size of the chunk (including the opcode). Thus, the
     21  * offset just prior to calling ReadOpAndSize + 'size' is the offset
     22  * to the next chunk's op code. This also means that the size of a chunk
     23  * with no arguments (just an opcode) will be 4.
     24  */
     25 DrawType SkPicturePlayback::ReadOpAndSize(SkReader32* reader, uint32_t* size) {
     26     uint32_t temp = reader->readInt();
     27     uint32_t op;
     28     if (((uint8_t)temp) == temp) {
     29         // old skp file - no size information
     30         op = temp;
     31         *size = 0;
     32     } else {
     33         UNPACK_8_24(temp, op, *size);
     34         if (MASK_24 == *size) {
     35             *size = reader->readInt();
     36         }
     37     }
     38     return (DrawType)op;
     39 }
     40 
     41 
     42 static const SkRect* get_rect_ptr(SkReader32* reader) {
     43     if (reader->readBool()) {
     44         return &reader->skipT<SkRect>();
     45     } else {
     46         return NULL;
     47     }
     48 }
     49 
     50 class TextContainer {
     51 public:
     52     size_t length() { return fByteLength; }
     53     const void* text() { return (const void*)fText; }
     54     size_t fByteLength;
     55     const char* fText;
     56 };
     57 
     58 void get_text(SkReader32* reader, TextContainer* text) {
     59     size_t length = text->fByteLength = reader->readInt();
     60     text->fText = (const char*)reader->skip(length);
     61 }
     62 
     63 // FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads.
     64 static SkBitmap shallow_copy(const SkBitmap& bitmap) {
     65     return bitmap;
     66 }
     67 
     68 void SkPicturePlayback::draw(SkCanvas* canvas, SkPicture::AbortCallback* callback) {
     69     AutoResetOpID aroi(this);
     70     SkASSERT(0 == fCurOffset);
     71 
     72     SkReader32 reader(fPictureData->opData()->bytes(), fPictureData->opData()->size());
     73 
     74     // Record this, so we can concat w/ it if we encounter a setMatrix()
     75     SkMatrix initialMatrix = canvas->getTotalMatrix();
     76 
     77     SkAutoCanvasRestore acr(canvas, false);
     78 
     79     while (!reader.eof()) {
     80         if (callback && callback->abort()) {
     81             return;
     82         }
     83 
     84         fCurOffset = reader.offset();
     85         uint32_t size;
     86         DrawType op = ReadOpAndSize(&reader, &size);
     87 
     88         this->handleOp(&reader, op, size, canvas, initialMatrix);
     89     }
     90 }
     91 
     92 void SkPicturePlayback::handleOp(SkReader32* reader,
     93                                  DrawType op,
     94                                  uint32_t size,
     95                                  SkCanvas* canvas,
     96                                  const SkMatrix& initialMatrix) {
     97     switch (op) {
     98         case NOOP: {
     99             SkASSERT(size >= 4);
    100             reader->skip(size - 4);
    101         } break;
    102         case CLIP_PATH: {
    103             const SkPath& path = fPictureData->getPath(reader);
    104             uint32_t packed = reader->readInt();
    105             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
    106             bool doAA = ClipParams_unpackDoAA(packed);
    107             size_t offsetToRestore = reader->readInt();
    108             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
    109             canvas->clipPath(path, regionOp, doAA);
    110             if (canvas->isClipEmpty() && offsetToRestore) {
    111                 reader->setOffset(offsetToRestore);
    112             }
    113         } break;
    114         case CLIP_REGION: {
    115             SkRegion region;
    116             reader->readRegion(&region);
    117             uint32_t packed = reader->readInt();
    118             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
    119             size_t offsetToRestore = reader->readInt();
    120             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
    121             canvas->clipRegion(region, regionOp);
    122             if (canvas->isClipEmpty() && offsetToRestore) {
    123                 reader->setOffset(offsetToRestore);
    124             }
    125         } break;
    126         case CLIP_RECT: {
    127             const SkRect& rect = reader->skipT<SkRect>();
    128             uint32_t packed = reader->readInt();
    129             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
    130             bool doAA = ClipParams_unpackDoAA(packed);
    131             size_t offsetToRestore = reader->readInt();
    132             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
    133             canvas->clipRect(rect, regionOp, doAA);
    134             if (canvas->isClipEmpty() && offsetToRestore) {
    135                 reader->setOffset(offsetToRestore);
    136             }
    137         } break;
    138         case CLIP_RRECT: {
    139             SkRRect rrect;
    140             reader->readRRect(&rrect);
    141             uint32_t packed = reader->readInt();
    142             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
    143             bool doAA = ClipParams_unpackDoAA(packed);
    144             size_t offsetToRestore = reader->readInt();
    145             SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset());
    146             canvas->clipRRect(rrect, regionOp, doAA);
    147             if (canvas->isClipEmpty() && offsetToRestore) {
    148                 reader->setOffset(offsetToRestore);
    149             }
    150         } break;
    151         case PUSH_CULL: break;  // Deprecated, safe to ignore both push and pop.
    152         case POP_CULL:  break;
    153         case CONCAT: {
    154             SkMatrix matrix;
    155             reader->readMatrix(&matrix);
    156             canvas->concat(matrix);
    157             break;
    158         }
    159         case DRAW_BITMAP: {
    160             const SkPaint* paint = fPictureData->getPaint(reader);
    161             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
    162             const SkPoint& loc = reader->skipT<SkPoint>();
    163             canvas->drawBitmap(bitmap, loc.fX, loc.fY, paint);
    164         } break;
    165         case DRAW_BITMAP_RECT_TO_RECT: {
    166             const SkPaint* paint = fPictureData->getPaint(reader);
    167             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
    168             const SkRect* src = get_rect_ptr(reader);   // may be null
    169             const SkRect& dst = reader->skipT<SkRect>();     // required
    170             SkCanvas::DrawBitmapRectFlags flags;
    171             flags = (SkCanvas::DrawBitmapRectFlags) reader->readInt();
    172             canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags);
    173         } break;
    174         case DRAW_BITMAP_MATRIX: {
    175             const SkPaint* paint = fPictureData->getPaint(reader);
    176             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
    177             SkMatrix matrix;
    178             reader->readMatrix(&matrix);
    179 
    180             SkAutoCanvasRestore acr(canvas, true);
    181             canvas->concat(matrix);
    182             canvas->drawBitmap(bitmap, 0, 0, paint);
    183         } break;
    184         case DRAW_BITMAP_NINE: {
    185             const SkPaint* paint = fPictureData->getPaint(reader);
    186             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
    187             const SkIRect& src = reader->skipT<SkIRect>();
    188             const SkRect& dst = reader->skipT<SkRect>();
    189             canvas->drawBitmapNine(bitmap, src, dst, paint);
    190         } break;
    191         case DRAW_CLEAR:
    192             canvas->clear(reader->readInt());
    193             break;
    194         case DRAW_DATA: {
    195             // This opcode is now dead, just need to skip it for backwards compatibility
    196             size_t length = reader->readInt();
    197             (void)reader->skip(length);
    198             // skip handles padding the read out to a multiple of 4
    199         } break;
    200         case DRAW_DRRECT: {
    201             const SkPaint& paint = *fPictureData->getPaint(reader);
    202             SkRRect outer, inner;
    203             reader->readRRect(&outer);
    204             reader->readRRect(&inner);
    205             canvas->drawDRRect(outer, inner, paint);
    206         } break;
    207         case BEGIN_COMMENT_GROUP: {
    208             const char* desc = reader->readString();
    209             canvas->beginCommentGroup(desc);
    210         } break;
    211         case COMMENT: {
    212             const char* kywd = reader->readString();
    213             const char* value = reader->readString();
    214             canvas->addComment(kywd, value);
    215         } break;
    216         case END_COMMENT_GROUP: {
    217             canvas->endCommentGroup();
    218         } break;
    219         case DRAW_OVAL: {
    220             const SkPaint& paint = *fPictureData->getPaint(reader);
    221             canvas->drawOval(reader->skipT<SkRect>(), paint);
    222         } break;
    223         case DRAW_PAINT:
    224             canvas->drawPaint(*fPictureData->getPaint(reader));
    225             break;
    226         case DRAW_PATCH: {
    227             const SkPaint& paint = *fPictureData->getPaint(reader);
    228 
    229             const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts *
    230                                                                  sizeof(SkPoint));
    231             uint32_t flag = reader->readInt();
    232             const SkColor* colors = NULL;
    233             if (flag & DRAW_VERTICES_HAS_COLORS) {
    234                 colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkColor));
    235             }
    236             const SkPoint* texCoords = NULL;
    237             if (flag & DRAW_VERTICES_HAS_TEXS) {
    238                 texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners *
    239                                                          sizeof(SkPoint));
    240             }
    241             SkAutoTUnref<SkXfermode> xfer;
    242             if (flag & DRAW_VERTICES_HAS_XFER) {
    243                 int mode = reader->readInt();
    244                 if (mode < 0 || mode > SkXfermode::kLastMode) {
    245                     mode = SkXfermode::kModulate_Mode;
    246                 }
    247                 xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
    248             }
    249             canvas->drawPatch(cubics, colors, texCoords, xfer, paint);
    250         } break;
    251         case DRAW_PATH: {
    252             const SkPaint& paint = *fPictureData->getPaint(reader);
    253             canvas->drawPath(fPictureData->getPath(reader), paint);
    254         } break;
    255         case DRAW_PICTURE:
    256             canvas->drawPicture(fPictureData->getPicture(reader));
    257             break;
    258         case DRAW_PICTURE_MATRIX_PAINT: {
    259             const SkPaint* paint = fPictureData->getPaint(reader);
    260             SkMatrix matrix;
    261             reader->readMatrix(&matrix);
    262             const SkPicture* pic = fPictureData->getPicture(reader);
    263             canvas->drawPicture(pic, &matrix, paint);
    264         } break;
    265         case DRAW_POINTS: {
    266             const SkPaint& paint = *fPictureData->getPaint(reader);
    267             SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt();
    268             size_t count = reader->readInt();
    269             const SkPoint* pts = (const SkPoint*)reader->skip(sizeof(SkPoint)* count);
    270             canvas->drawPoints(mode, count, pts, paint);
    271         } break;
    272         case DRAW_POS_TEXT: {
    273             const SkPaint& paint = *fPictureData->getPaint(reader);
    274             TextContainer text;
    275             get_text(reader, &text);
    276             size_t points = reader->readInt();
    277             const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
    278             canvas->drawPosText(text.text(), text.length(), pos, paint);
    279         } break;
    280         case DRAW_POS_TEXT_TOP_BOTTOM: {
    281             const SkPaint& paint = *fPictureData->getPaint(reader);
    282             TextContainer text;
    283             get_text(reader, &text);
    284             size_t points = reader->readInt();
    285             const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
    286             const SkScalar top = reader->readScalar();
    287             const SkScalar bottom = reader->readScalar();
    288             if (!canvas->quickRejectY(top, bottom)) {
    289                 canvas->drawPosText(text.text(), text.length(), pos, paint);
    290             }
    291         } break;
    292         case DRAW_POS_TEXT_H: {
    293             const SkPaint& paint = *fPictureData->getPaint(reader);
    294             TextContainer text;
    295             get_text(reader, &text);
    296             size_t xCount = reader->readInt();
    297             const SkScalar constY = reader->readScalar();
    298             const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar));
    299             canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint);
    300         } break;
    301         case DRAW_POS_TEXT_H_TOP_BOTTOM: {
    302             const SkPaint& paint = *fPictureData->getPaint(reader);
    303             TextContainer text;
    304             get_text(reader, &text);
    305             size_t xCount = reader->readInt();
    306             const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar));
    307             const SkScalar top = *xpos++;
    308             const SkScalar bottom = *xpos++;
    309             const SkScalar constY = *xpos++;
    310             if (!canvas->quickRejectY(top, bottom)) {
    311                 canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint);
    312             }
    313         } break;
    314         case DRAW_RECT: {
    315             const SkPaint& paint = *fPictureData->getPaint(reader);
    316             canvas->drawRect(reader->skipT<SkRect>(), paint);
    317         } break;
    318         case DRAW_RRECT: {
    319             const SkPaint& paint = *fPictureData->getPaint(reader);
    320             SkRRect rrect;
    321             reader->readRRect(&rrect);
    322             canvas->drawRRect(rrect, paint);
    323         } break;
    324         case DRAW_SPRITE: {
    325             const SkPaint* paint = fPictureData->getPaint(reader);
    326             const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader));
    327             int left = reader->readInt();
    328             int top = reader->readInt();
    329             canvas->drawSprite(bitmap, left, top, paint);
    330         } break;
    331         case DRAW_TEXT: {
    332             const SkPaint& paint = *fPictureData->getPaint(reader);
    333             TextContainer text;
    334             get_text(reader, &text);
    335             SkScalar x = reader->readScalar();
    336             SkScalar y = reader->readScalar();
    337             canvas->drawText(text.text(), text.length(), x, y, paint);
    338         } break;
    339         case DRAW_TEXT_BLOB: {
    340             const SkPaint& paint = *fPictureData->getPaint(reader);
    341             const SkTextBlob* blob = fPictureData->getTextBlob(reader);
    342             SkScalar x = reader->readScalar();
    343             SkScalar y = reader->readScalar();
    344             canvas->drawTextBlob(blob, x, y, paint);
    345         } break;
    346         case DRAW_TEXT_TOP_BOTTOM: {
    347             const SkPaint& paint = *fPictureData->getPaint(reader);
    348             TextContainer text;
    349             get_text(reader, &text);
    350             const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar));
    351             // ptr[0] == x
    352             // ptr[1] == y
    353             // ptr[2] == top
    354             // ptr[3] == bottom
    355             if (!canvas->quickRejectY(ptr[2], ptr[3])) {
    356                 canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], paint);
    357             }
    358         } break;
    359         case DRAW_TEXT_ON_PATH: {
    360             const SkPaint& paint = *fPictureData->getPaint(reader);
    361             TextContainer text;
    362             get_text(reader, &text);
    363             const SkPath& path = fPictureData->getPath(reader);
    364             SkMatrix matrix;
    365             reader->readMatrix(&matrix);
    366             canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, paint);
    367         } break;
    368         case DRAW_VERTICES: {
    369             SkAutoTUnref<SkXfermode> xfer;
    370             const SkPaint& paint = *fPictureData->getPaint(reader);
    371             DrawVertexFlags flags = (DrawVertexFlags)reader->readInt();
    372             SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt();
    373             int vCount = reader->readInt();
    374             const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
    375             const SkPoint* texs = NULL;
    376             const SkColor* colors = NULL;
    377             const uint16_t* indices = NULL;
    378             int iCount = 0;
    379             if (flags & DRAW_VERTICES_HAS_TEXS) {
    380                 texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
    381             }
    382             if (flags & DRAW_VERTICES_HAS_COLORS) {
    383                 colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor));
    384             }
    385             if (flags & DRAW_VERTICES_HAS_INDICES) {
    386                 iCount = reader->readInt();
    387                 indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t));
    388             }
    389             if (flags & DRAW_VERTICES_HAS_XFER) {
    390                 int mode = reader->readInt();
    391                 if (mode < 0 || mode > SkXfermode::kLastMode) {
    392                     mode = SkXfermode::kModulate_Mode;
    393                 }
    394                 xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
    395             }
    396             canvas->drawVertices(vmode, vCount, verts, texs, colors, xfer, indices, iCount, paint);
    397         } break;
    398         case RESTORE:
    399             canvas->restore();
    400             break;
    401         case ROTATE:
    402             canvas->rotate(reader->readScalar());
    403             break;
    404         case SAVE:
    405             // SKPs with version < 29 also store a SaveFlags param.
    406             if (size > 4) {
    407                 SkASSERT(8 == size);
    408                 reader->readInt();
    409             }
    410             canvas->save();
    411             break;
    412         case SAVE_LAYER: {
    413             const SkRect* boundsPtr = get_rect_ptr(reader);
    414             const SkPaint* paint = fPictureData->getPaint(reader);
    415             canvas->saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader->readInt());
    416         } break;
    417         case SCALE: {
    418             SkScalar sx = reader->readScalar();
    419             SkScalar sy = reader->readScalar();
    420             canvas->scale(sx, sy);
    421         } break;
    422         case SET_MATRIX: {
    423             SkMatrix matrix;
    424             reader->readMatrix(&matrix);
    425             matrix.postConcat(initialMatrix);
    426             canvas->setMatrix(matrix);
    427         } break;
    428         case SKEW: {
    429             SkScalar sx = reader->readScalar();
    430             SkScalar sy = reader->readScalar();
    431             canvas->skew(sx, sy);
    432         } break;
    433         case TRANSLATE: {
    434             SkScalar dx = reader->readScalar();
    435             SkScalar dy = reader->readScalar();
    436             canvas->translate(dx, dy);
    437         } break;
    438         default:
    439             SkASSERTF(false, "Unknown draw type: %d", op);
    440     }
    441 }
    442 
    443