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(®ion); 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