1 2 /* 3 * Copyright 2007 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "SkPictureFlat.h" 11 #include "SkPicturePlayback.h" 12 #include "SkPictureRecord.h" 13 14 #include "SkBBHFactory.h" 15 #include "SkBitmapDevice.h" 16 #include "SkCanvas.h" 17 #include "SkChunkAlloc.h" 18 #include "SkPaintPriv.h" 19 #include "SkPicture.h" 20 #include "SkRegion.h" 21 #include "SkStream.h" 22 #include "SkTDArray.h" 23 #include "SkTSearch.h" 24 #include "SkTime.h" 25 26 #include "SkReader32.h" 27 #include "SkWriter32.h" 28 #include "SkRTree.h" 29 #include "SkBBoxHierarchyRecord.h" 30 31 #if SK_SUPPORT_GPU 32 #include "GrContext.h" 33 #endif 34 35 template <typename T> int SafeCount(const T* obj) { 36 return obj ? obj->count() : 0; 37 } 38 39 #define DUMP_BUFFER_SIZE 65536 40 41 //#define ENABLE_TIME_DRAW // dumps milliseconds for each draw 42 43 44 #ifdef SK_DEBUG 45 // enable SK_DEBUG_TRACE to trace DrawType elements when 46 // recorded and played back 47 // #define SK_DEBUG_TRACE 48 // enable SK_DEBUG_SIZE to see the size of picture components 49 // #define SK_DEBUG_SIZE 50 // enable SK_DEBUG_DUMP to see the contents of recorded elements 51 // #define SK_DEBUG_DUMP 52 // enable SK_DEBUG_VALIDATE to check internal structures for consistency 53 // #define SK_DEBUG_VALIDATE 54 #endif 55 56 #if defined SK_DEBUG_TRACE || defined SK_DEBUG_DUMP 57 const char* DrawTypeToString(DrawType drawType) { 58 switch (drawType) { 59 case UNUSED: SkDebugf("DrawType UNUSED\n"); SkASSERT(0); break; 60 case CLIP_PATH: return "CLIP_PATH"; 61 case CLIP_REGION: return "CLIP_REGION"; 62 case CLIP_RECT: return "CLIP_RECT"; 63 case CLIP_RRECT: return "CLIP_RRECT"; 64 case CONCAT: return "CONCAT"; 65 case DRAW_BITMAP: return "DRAW_BITMAP"; 66 case DRAW_BITMAP_MATRIX: return "DRAW_BITMAP_MATRIX"; 67 case DRAW_BITMAP_NINE: return "DRAW_BITMAP_NINE"; 68 case DRAW_BITMAP_RECT_TO_RECT: return "DRAW_BITMAP_RECT_TO_RECT"; 69 case DRAW_CLEAR: return "DRAW_CLEAR"; 70 case DRAW_DATA: return "DRAW_DATA"; 71 case DRAW_OVAL: return "DRAW_OVAL"; 72 case DRAW_PAINT: return "DRAW_PAINT"; 73 case DRAW_PATH: return "DRAW_PATH"; 74 case DRAW_PICTURE: return "DRAW_PICTURE"; 75 case DRAW_POINTS: return "DRAW_POINTS"; 76 case DRAW_POS_TEXT: return "DRAW_POS_TEXT"; 77 case DRAW_POS_TEXT_TOP_BOTTOM: return "DRAW_POS_TEXT_TOP_BOTTOM"; 78 case DRAW_POS_TEXT_H: return "DRAW_POS_TEXT_H"; 79 case DRAW_POS_TEXT_H_TOP_BOTTOM: return "DRAW_POS_TEXT_H_TOP_BOTTOM"; 80 case DRAW_RECT: return "DRAW_RECT"; 81 case DRAW_RRECT: return "DRAW_RRECT"; 82 case DRAW_SPRITE: return "DRAW_SPRITE"; 83 case DRAW_TEXT: return "DRAW_TEXT"; 84 case DRAW_TEXT_ON_PATH: return "DRAW_TEXT_ON_PATH"; 85 case DRAW_TEXT_TOP_BOTTOM: return "DRAW_TEXT_TOP_BOTTOM"; 86 case DRAW_VERTICES: return "DRAW_VERTICES"; 87 case RESTORE: return "RESTORE"; 88 case ROTATE: return "ROTATE"; 89 case SAVE: return "SAVE"; 90 case SAVE_LAYER: return "SAVE_LAYER"; 91 case SCALE: return "SCALE"; 92 case SET_MATRIX: return "SET_MATRIX"; 93 case SKEW: return "SKEW"; 94 case TRANSLATE: return "TRANSLATE"; 95 case NOOP: return "NOOP"; 96 default: 97 SkDebugf("DrawType error 0x%08x\n", drawType); 98 SkASSERT(0); 99 break; 100 } 101 SkASSERT(0); 102 return NULL; 103 } 104 #endif 105 106 #ifdef SK_DEBUG_VALIDATE 107 static void validateMatrix(const SkMatrix* matrix) { 108 SkScalar scaleX = matrix->getScaleX(); 109 SkScalar scaleY = matrix->getScaleY(); 110 SkScalar skewX = matrix->getSkewX(); 111 SkScalar skewY = matrix->getSkewY(); 112 SkScalar perspX = matrix->getPerspX(); 113 SkScalar perspY = matrix->getPerspY(); 114 if (scaleX != 0 && skewX != 0) 115 SkDebugf("scaleX != 0 && skewX != 0\n"); 116 SkASSERT(scaleX == 0 || skewX == 0); 117 SkASSERT(scaleY == 0 || skewY == 0); 118 SkASSERT(perspX == 0); 119 SkASSERT(perspY == 0); 120 } 121 #endif 122 123 124 /////////////////////////////////////////////////////////////////////////////// 125 126 SkPicture::SkPicture() 127 : fAccelData(NULL) { 128 this->needsNewGenID(); 129 fPlayback = NULL; 130 fWidth = fHeight = 0; 131 } 132 133 SkPicture::SkPicture(int width, int height, 134 const SkPictureRecord& record, 135 bool deepCopyOps) 136 : fWidth(width) 137 , fHeight(height) 138 , fAccelData(NULL) { 139 this->needsNewGenID(); 140 141 SkPictInfo info; 142 this->createHeader(&info); 143 fPlayback = SkNEW_ARGS(SkPicturePlayback, (record, info, deepCopyOps)); 144 } 145 146 SkPicture::SkPicture(const SkPicture& src) 147 : INHERITED() 148 , fAccelData(NULL) { 149 this->needsNewGenID(); 150 fWidth = src.fWidth; 151 fHeight = src.fHeight; 152 153 if (src.fPlayback) { 154 fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback)); 155 fUniqueID = src.uniqueID(); // need to call method to ensure != 0 156 } else { 157 fPlayback = NULL; 158 } 159 } 160 161 SkPicture::~SkPicture() { 162 SkDELETE(fPlayback); 163 SkSafeUnref(fAccelData); 164 } 165 166 void SkPicture::swap(SkPicture& other) { 167 SkTSwap(fUniqueID, other.fUniqueID); 168 SkTSwap(fPlayback, other.fPlayback); 169 SkTSwap(fAccelData, other.fAccelData); 170 SkTSwap(fWidth, other.fWidth); 171 SkTSwap(fHeight, other.fHeight); 172 } 173 174 SkPicture* SkPicture::clone() const { 175 SkPicture* clonedPicture = SkNEW(SkPicture); 176 this->clone(clonedPicture, 1); 177 return clonedPicture; 178 } 179 180 void SkPicture::clone(SkPicture* pictures, int count) const { 181 SkPictCopyInfo copyInfo; 182 183 for (int i = 0; i < count; i++) { 184 SkPicture* clone = &pictures[i]; 185 186 clone->needsNewGenID(); 187 clone->fWidth = fWidth; 188 clone->fHeight = fHeight; 189 SkDELETE(clone->fPlayback); 190 191 /* We want to copy the src's playback. However, if that hasn't been built 192 yet, we need to fake a call to endRecording() without actually calling 193 it (since it is destructive, and we don't want to change src). 194 */ 195 if (fPlayback) { 196 if (!copyInfo.initialized) { 197 int paintCount = SafeCount(fPlayback->fPaints); 198 199 /* The alternative to doing this is to have a clone method on the paint and have it 200 * make the deep copy of its internal structures as needed. The holdup to doing 201 * that is at this point we would need to pass the SkBitmapHeap so that we don't 202 * unnecessarily flatten the pixels in a bitmap shader. 203 */ 204 copyInfo.paintData.setCount(paintCount); 205 206 /* Use an SkBitmapHeap to avoid flattening bitmaps in shaders. If there already is 207 * one, use it. If this SkPicturePlayback was created from a stream, fBitmapHeap 208 * will be NULL, so create a new one. 209 */ 210 if (fPlayback->fBitmapHeap.get() == NULL) { 211 // FIXME: Put this on the stack inside SkPicture::clone. 212 SkBitmapHeap* heap = SkNEW(SkBitmapHeap); 213 copyInfo.controller.setBitmapStorage(heap); 214 heap->unref(); 215 } else { 216 copyInfo.controller.setBitmapStorage(fPlayback->fBitmapHeap); 217 } 218 219 SkDEBUGCODE(int heapSize = SafeCount(fPlayback->fBitmapHeap.get());) 220 for (int i = 0; i < paintCount; i++) { 221 if (NeedsDeepCopy(fPlayback->fPaints->at(i))) { 222 copyInfo.paintData[i] = 223 SkFlatData::Create<SkPaint::FlatteningTraits>(©Info.controller, 224 fPlayback->fPaints->at(i), 0); 225 226 } else { 227 // this is our sentinel, which we use in the unflatten loop 228 copyInfo.paintData[i] = NULL; 229 } 230 } 231 SkASSERT(SafeCount(fPlayback->fBitmapHeap.get()) == heapSize); 232 233 // needed to create typeface playback 234 copyInfo.controller.setupPlaybacks(); 235 copyInfo.initialized = true; 236 } 237 238 clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fPlayback, ©Info)); 239 clone->fUniqueID = this->uniqueID(); // need to call method to ensure != 0 240 } else { 241 clone->fPlayback = NULL; 242 } 243 } 244 } 245 246 SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() { 247 static int32_t gNextID = 0; 248 249 int32_t id = sk_atomic_inc(&gNextID); 250 if (id >= 1 << (8 * sizeof(Domain))) { 251 SK_CRASH(); 252 } 253 254 return static_cast<Domain>(id); 255 } 256 257 /////////////////////////////////////////////////////////////////////////////// 258 259 const SkPicture::OperationList& SkPicture::OperationList::InvalidList() { 260 static OperationList gInvalid; 261 return gInvalid; 262 } 263 264 const SkPicture::OperationList& SkPicture::EXPERIMENTAL_getActiveOps(const SkIRect& queryRect) const { 265 SkASSERT(NULL != fPlayback); 266 if (NULL != fPlayback) { 267 return fPlayback->getActiveOps(queryRect); 268 } 269 return OperationList::InvalidList(); 270 } 271 272 size_t SkPicture::EXPERIMENTAL_curOpID() const { 273 if (NULL != fPlayback) { 274 return fPlayback->curOpID(); 275 } 276 return 0; 277 } 278 279 void SkPicture::draw(SkCanvas* surface, SkDrawPictureCallback* callback) const { 280 SkASSERT(NULL != fPlayback); 281 if (NULL != fPlayback) { 282 fPlayback->draw(*surface, callback); 283 } 284 } 285 286 /////////////////////////////////////////////////////////////////////////////// 287 288 #include "SkStream.h" 289 290 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' }; 291 292 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) { 293 if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) { 294 return false; 295 } 296 297 if (info.fVersion < MIN_PICTURE_VERSION || 298 info.fVersion > CURRENT_PICTURE_VERSION) { 299 return false; 300 } 301 302 return true; 303 } 304 305 bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) { 306 if (NULL == stream) { 307 return false; 308 } 309 310 // Check magic bytes. 311 SkPictInfo info; 312 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); 313 if (!stream->read(&info, sizeof(info)) || !IsValidPictInfo(info)) { 314 return false; 315 } 316 317 if (pInfo != NULL) { 318 *pInfo = info; 319 } 320 return true; 321 } 322 323 bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer& buffer, SkPictInfo* pInfo) { 324 // Check magic bytes. 325 SkPictInfo info; 326 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); 327 if (!buffer.readByteArray(&info, sizeof(info)) || !IsValidPictInfo(info)) { 328 return false; 329 } 330 331 if (pInfo != NULL) { 332 *pInfo = info; 333 } 334 return true; 335 } 336 337 SkPicture::SkPicture(SkPicturePlayback* playback, int width, int height) 338 : fPlayback(playback) 339 , fWidth(width) 340 , fHeight(height) 341 , fAccelData(NULL) { 342 this->needsNewGenID(); 343 } 344 345 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc proc) { 346 SkPictInfo info; 347 348 if (!InternalOnly_StreamIsSKP(stream, &info)) { 349 return NULL; 350 } 351 352 // Check to see if there is a playback to recreate. 353 if (stream->readBool()) { 354 SkPicturePlayback* playback = SkPicturePlayback::CreateFromStream(stream, info, proc); 355 if (NULL == playback) { 356 return NULL; 357 } 358 359 return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight)); 360 } 361 362 return NULL; 363 } 364 365 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) { 366 SkPictInfo info; 367 368 if (!InternalOnly_BufferIsSKP(buffer, &info)) { 369 return NULL; 370 } 371 372 // Check to see if there is a playback to recreate. 373 if (buffer.readBool()) { 374 SkPicturePlayback* playback = SkPicturePlayback::CreateFromBuffer(buffer, info); 375 if (NULL == playback) { 376 return NULL; 377 } 378 379 return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight)); 380 } 381 382 return NULL; 383 } 384 385 void SkPicture::createHeader(SkPictInfo* info) const { 386 // Copy magic bytes at the beginning of the header 387 SkASSERT(sizeof(kMagic) == 8); 388 SkASSERT(sizeof(kMagic) == sizeof(info->fMagic)); 389 memcpy(info->fMagic, kMagic, sizeof(kMagic)); 390 391 // Set picture info after magic bytes in the header 392 info->fVersion = CURRENT_PICTURE_VERSION; 393 info->fWidth = fWidth; 394 info->fHeight = fHeight; 395 info->fFlags = SkPictInfo::kCrossProcess_Flag; 396 // TODO: remove this flag, since we're always float (now) 397 info->fFlags |= SkPictInfo::kScalarIsFloat_Flag; 398 399 if (8 == sizeof(void*)) { 400 info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag; 401 } 402 } 403 404 void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const { 405 SkPicturePlayback* playback = fPlayback; 406 407 SkPictInfo info; 408 this->createHeader(&info); 409 stream->write(&info, sizeof(info)); 410 if (playback) { 411 stream->writeBool(true); 412 playback->serialize(stream, encoder); 413 // delete playback if it is a local version (i.e. cons'd up just now) 414 if (playback != fPlayback) { 415 SkDELETE(playback); 416 } 417 } else { 418 stream->writeBool(false); 419 } 420 } 421 422 void SkPicture::WriteTagSize(SkWriteBuffer& buffer, uint32_t tag, size_t size) { 423 buffer.writeUInt(tag); 424 buffer.writeUInt(SkToU32(size)); 425 } 426 427 void SkPicture::WriteTagSize(SkWStream* stream, uint32_t tag, size_t size) { 428 stream->write32(tag); 429 stream->write32(SkToU32(size)); 430 } 431 432 void SkPicture::flatten(SkWriteBuffer& buffer) const { 433 SkPicturePlayback* playback = fPlayback; 434 435 SkPictInfo info; 436 this->createHeader(&info); 437 buffer.writeByteArray(&info, sizeof(info)); 438 if (playback) { 439 buffer.writeBool(true); 440 playback->flatten(buffer); 441 // delete playback if it is a local version (i.e. cons'd up just now) 442 if (playback != fPlayback) { 443 SkDELETE(playback); 444 } 445 } else { 446 buffer.writeBool(false); 447 } 448 } 449 450 #if SK_SUPPORT_GPU 451 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **reason) const { 452 if (NULL == fPlayback) { 453 if (NULL != reason) { 454 *reason = "Missing playback object."; 455 } 456 return false; 457 } 458 459 return fPlayback->suitableForGpuRasterization(context, reason); 460 } 461 #endif 462 463 bool SkPicture::willPlayBackBitmaps() const { 464 if (!fPlayback) { 465 return false; 466 } 467 return fPlayback->containsBitmaps(); 468 } 469 470 #ifdef SK_BUILD_FOR_ANDROID 471 void SkPicture::abortPlayback() { 472 if (NULL == fPlayback) { 473 return; 474 } 475 fPlayback->abort(); 476 } 477 #endif 478 479 static int32_t next_picture_generation_id() { 480 static int32_t gPictureGenerationID = 0; 481 // do a loop in case our global wraps around, as we never want to 482 // return a 0 483 int32_t genID; 484 do { 485 genID = sk_atomic_inc(&gPictureGenerationID) + 1; 486 } while (SK_InvalidGenID == genID); 487 return genID; 488 } 489 490 uint32_t SkPicture::uniqueID() const { 491 if (SK_InvalidGenID == fUniqueID) { 492 fUniqueID = next_picture_generation_id(); 493 } 494 return fUniqueID; 495 } 496