SkPictureData.cpp revision 5bc760a6a6a61ff462a204e0c051ad6147760223
1/* 2 * Copyright 2011 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#include <new> 8#include "SkBBoxHierarchy.h" 9#include "SkDrawPictureCallback.h" 10#include "SkPictureData.h" 11#include "SkPictureRecord.h" 12#include "SkReadBuffer.h" 13#include "SkTextBlob.h" 14#include "SkTypeface.h" 15#include "SkTSort.h" 16#include "SkWriteBuffer.h" 17 18#if SK_SUPPORT_GPU 19#include "GrContext.h" 20#endif 21 22template <typename T> int SafeCount(const T* obj) { 23 return obj ? obj->count() : 0; 24} 25 26SkPictureData::SkPictureData(const SkPictInfo& info) 27 : fInfo(info) { 28 this->init(); 29} 30 31void SkPictureData::initForPlayback() const { 32 // ensure that the paths bounds are pre-computed 33 if (fPathHeap.get()) { 34 for (int i = 0; i < fPathHeap->count(); i++) { 35 (*fPathHeap.get())[i].updateBoundsCache(); 36 } 37 } 38} 39 40SkPictureData::SkPictureData(const SkPictureRecord& record, 41 const SkPictInfo& info, 42 bool deepCopyOps) 43 : fInfo(info) { 44 45 this->init(); 46 47 fOpData = record.opData(deepCopyOps); 48 49 fBoundingHierarchy = record.fBoundingHierarchy; 50 fStateTree = record.fStateTree; 51 52 SkSafeRef(fBoundingHierarchy); 53 SkSafeRef(fStateTree); 54 fContentInfo.set(record.fContentInfo); 55 56 if (fBoundingHierarchy) { 57 fBoundingHierarchy->flushDeferredInserts(); 58 } 59 60 // copy over the refcnt dictionary to our reader 61 record.fFlattenableHeap.setupPlaybacks(); 62 63 fBitmaps = record.fBitmapHeap->extractBitmaps(); 64 fPaints = record.fPaints.unflattenToArray(); 65 66 fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap)); 67 fPathHeap.reset(SkSafeRef(record.pathHeap())); 68 69 this->initForPlayback(); 70 71 const SkTDArray<const SkPicture* >& pictures = record.getPictureRefs(); 72 fPictureCount = pictures.count(); 73 if (fPictureCount > 0) { 74 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount); 75 for (int i = 0; i < fPictureCount; i++) { 76 fPictureRefs[i] = pictures[i]; 77 fPictureRefs[i]->ref(); 78 } 79 } 80 81 // templatize to consolidate with similar picture logic? 82 const SkTDArray<const SkTextBlob*>& blobs = record.getTextBlobRefs(); 83 fTextBlobCount = blobs.count(); 84 if (fTextBlobCount > 0) { 85 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount); 86 for (int i = 0; i < fTextBlobCount; ++i) { 87 fTextBlobRefs[i] = SkRef(blobs[i]); 88 } 89 } 90} 91 92void SkPictureData::init() { 93 fBitmaps = NULL; 94 fPaints = NULL; 95 fPictureRefs = NULL; 96 fPictureCount = 0; 97 fTextBlobRefs = NULL; 98 fTextBlobCount = 0; 99 fOpData = NULL; 100 fFactoryPlayback = NULL; 101 fBoundingHierarchy = NULL; 102 fStateTree = NULL; 103} 104 105SkPictureData::~SkPictureData() { 106 SkSafeUnref(fOpData); 107 108 SkSafeUnref(fBitmaps); 109 SkSafeUnref(fPaints); 110 SkSafeUnref(fBoundingHierarchy); 111 SkSafeUnref(fStateTree); 112 113 for (int i = 0; i < fPictureCount; i++) { 114 fPictureRefs[i]->unref(); 115 } 116 SkDELETE_ARRAY(fPictureRefs); 117 118 for (int i = 0; i < fTextBlobCount; i++) { 119 fTextBlobRefs[i]->unref(); 120 } 121 SkDELETE_ARRAY(fTextBlobRefs); 122 123 SkDELETE(fFactoryPlayback); 124} 125 126bool SkPictureData::containsBitmaps() const { 127 if (fBitmaps && fBitmaps->count() > 0) { 128 return true; 129 } 130 for (int i = 0; i < fPictureCount; ++i) { 131 if (fPictureRefs[i]->willPlayBackBitmaps()) { 132 return true; 133 } 134 } 135 return false; 136} 137 138/////////////////////////////////////////////////////////////////////////////// 139/////////////////////////////////////////////////////////////////////////////// 140 141#include "SkStream.h" 142 143static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) { 144 size_t size = 4; // for 'count' 145 146 for (int i = 0; i < count; i++) { 147 const char* name = SkFlattenable::FactoryToName(array[i]); 148 if (NULL == name || 0 == *name) { 149 size += SkWStream::SizeOfPackedUInt(0); 150 } else { 151 size_t len = strlen(name); 152 size += SkWStream::SizeOfPackedUInt(len); 153 size += len; 154 } 155 } 156 157 return size; 158} 159 160static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, size_t size) { 161 buffer.writeUInt(tag); 162 buffer.writeUInt(SkToU32(size)); 163} 164 165static void write_tag_size(SkWStream* stream, uint32_t tag, size_t size) { 166 stream->write32(tag); 167 stream->write32(SkToU32(size)); 168} 169 170void SkPictureData::WriteFactories(SkWStream* stream, const SkFactorySet& rec) { 171 int count = rec.count(); 172 173 SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count); 174 SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get(); 175 rec.copyToArray(array); 176 177 size_t size = compute_chunk_size(array, count); 178 179 // TODO: write_tag_size should really take a size_t 180 write_tag_size(stream, SK_PICT_FACTORY_TAG, (uint32_t) size); 181 SkDEBUGCODE(size_t start = stream->bytesWritten()); 182 stream->write32(count); 183 184 for (int i = 0; i < count; i++) { 185 const char* name = SkFlattenable::FactoryToName(array[i]); 186 if (NULL == name || 0 == *name) { 187 stream->writePackedUInt(0); 188 } else { 189 size_t len = strlen(name); 190 stream->writePackedUInt(len); 191 stream->write(name, len); 192 } 193 } 194 195 SkASSERT(size == (stream->bytesWritten() - start)); 196} 197 198void SkPictureData::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) { 199 int count = rec.count(); 200 201 write_tag_size(stream, SK_PICT_TYPEFACE_TAG, count); 202 203 SkAutoSTMalloc<16, SkTypeface*> storage(count); 204 SkTypeface** array = (SkTypeface**)storage.get(); 205 rec.copyToArray((SkRefCnt**)array); 206 207 for (int i = 0; i < count; i++) { 208 array[i]->serialize(stream); 209 } 210} 211 212void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const { 213 int i, n; 214 215 if ((n = SafeCount(fBitmaps)) > 0) { 216 write_tag_size(buffer, SK_PICT_BITMAP_BUFFER_TAG, n); 217 for (i = 0; i < n; i++) { 218 buffer.writeBitmap((*fBitmaps)[i]); 219 } 220 } 221 222 if ((n = SafeCount(fPaints)) > 0) { 223 write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, n); 224 for (i = 0; i < n; i++) { 225 buffer.writePaint((*fPaints)[i]); 226 } 227 } 228 229 if ((n = SafeCount(fPathHeap.get())) > 0) { 230 write_tag_size(buffer, SK_PICT_PATH_BUFFER_TAG, n); 231 fPathHeap->flatten(buffer); 232 } 233 234 if (fTextBlobCount > 0) { 235 write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobCount); 236 for (i = 0; i < fTextBlobCount; ++i) { 237 fTextBlobRefs[i]->flatten(buffer); 238 } 239 } 240} 241 242void SkPictureData::serialize(SkWStream* stream, 243 SkPicture::EncodeBitmap encoder) const { 244 write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size()); 245 stream->write(fOpData->bytes(), fOpData->size()); 246 247 if (fPictureCount > 0) { 248 write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount); 249 for (int i = 0; i < fPictureCount; i++) { 250 fPictureRefs[i]->serialize(stream, encoder); 251 } 252 } 253 254 // Write some of our data into a writebuffer, and then serialize that 255 // into our stream 256 { 257 SkRefCntSet typefaceSet; 258 SkFactorySet factSet; 259 260 SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag); 261 buffer.setTypefaceRecorder(&typefaceSet); 262 buffer.setFactoryRecorder(&factSet); 263 buffer.setBitmapEncoder(encoder); 264 265 this->flattenToBuffer(buffer); 266 267 // We have to write these two sets into the stream *before* we write 268 // the buffer, since parsing that buffer will require that we already 269 // have these sets available to use. 270 WriteFactories(stream, factSet); 271 WriteTypefaces(stream, typefaceSet); 272 273 write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten()); 274 buffer.writeToStream(stream); 275 } 276 277 stream->write32(SK_PICT_EOF_TAG); 278} 279 280void SkPictureData::flatten(SkWriteBuffer& buffer) const { 281 write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size()); 282 buffer.writeByteArray(fOpData->bytes(), fOpData->size()); 283 284 if (fPictureCount > 0) { 285 write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictureCount); 286 for (int i = 0; i < fPictureCount; i++) { 287 fPictureRefs[i]->flatten(buffer); 288 } 289 } 290 291 // Write this picture playback's data into a writebuffer 292 this->flattenToBuffer(buffer); 293 buffer.write32(SK_PICT_EOF_TAG); 294} 295 296/////////////////////////////////////////////////////////////////////////////// 297 298/** 299 * Return the corresponding SkReadBuffer flags, given a set of 300 * SkPictInfo flags. 301 */ 302static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) { 303 static const struct { 304 uint32_t fSrc; 305 uint32_t fDst; 306 } gSD[] = { 307 { SkPictInfo::kCrossProcess_Flag, SkReadBuffer::kCrossProcess_Flag }, 308 { SkPictInfo::kScalarIsFloat_Flag, SkReadBuffer::kScalarIsFloat_Flag }, 309 { SkPictInfo::kPtrIs64Bit_Flag, SkReadBuffer::kPtrIs64Bit_Flag }, 310 }; 311 312 uint32_t rbMask = 0; 313 for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) { 314 if (pictInfoFlags & gSD[i].fSrc) { 315 rbMask |= gSD[i].fDst; 316 } 317 } 318 return rbMask; 319} 320 321bool SkPictureData::parseStreamTag(SkStream* stream, 322 uint32_t tag, 323 uint32_t size, 324 SkPicture::InstallPixelRefProc proc) { 325 /* 326 * By the time we encounter BUFFER_SIZE_TAG, we need to have already seen 327 * its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required 328 * but if they are present, they need to have been seen before the buffer. 329 * 330 * We assert that if/when we see either of these, that we have not yet seen 331 * the buffer tag, because if we have, then its too-late to deal with the 332 * factories or typefaces. 333 */ 334 SkDEBUGCODE(bool haveBuffer = false;) 335 336 switch (tag) { 337 case SK_PICT_READER_TAG: 338 SkASSERT(NULL == fOpData); 339 fOpData = SkData::NewFromStream(stream, size); 340 if (!fOpData) { 341 return false; 342 } 343 break; 344 case SK_PICT_FACTORY_TAG: { 345 SkASSERT(!haveBuffer); 346 // Remove this code when v21 and below are no longer supported. At the 347 // same time add a new 'count' variable and use it rather then reusing 'size'. 348#ifndef DISABLE_V21_COMPATIBILITY_CODE 349 if (fInfo.fVersion >= 22) { 350 // in v22 this tag's size represents the size of the chunk in bytes 351 // and the number of factory strings is written out separately 352#endif 353 size = stream->readU32(); 354#ifndef DISABLE_V21_COMPATIBILITY_CODE 355 } 356#endif 357 fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size)); 358 for (size_t i = 0; i < size; i++) { 359 SkString str; 360 const size_t len = stream->readPackedUInt(); 361 str.resize(len); 362 if (stream->read(str.writable_str(), len) != len) { 363 return false; 364 } 365 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str()); 366 } 367 } break; 368 case SK_PICT_TYPEFACE_TAG: { 369 SkASSERT(!haveBuffer); 370 const int count = SkToInt(size); 371 fTFPlayback.setCount(count); 372 for (int i = 0; i < count; i++) { 373 SkAutoTUnref<SkTypeface> tf(SkTypeface::Deserialize(stream)); 374 if (!tf.get()) { // failed to deserialize 375 // fTFPlayback asserts it never has a null, so we plop in 376 // the default here. 377 tf.reset(SkTypeface::RefDefault()); 378 } 379 fTFPlayback.set(i, tf); 380 } 381 } break; 382 case SK_PICT_PICTURE_TAG: { 383 fPictureCount = size; 384 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount); 385 bool success = true; 386 int i = 0; 387 for ( ; i < fPictureCount; i++) { 388 fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc); 389 if (NULL == fPictureRefs[i]) { 390 success = false; 391 break; 392 } 393 } 394 if (!success) { 395 // Delete all of the pictures that were already created (up to but excluding i): 396 for (int j = 0; j < i; j++) { 397 fPictureRefs[j]->unref(); 398 } 399 // Delete the array 400 SkDELETE_ARRAY(fPictureRefs); 401 fPictureCount = 0; 402 return false; 403 } 404 } break; 405 case SK_PICT_BUFFER_SIZE_TAG: { 406 SkAutoMalloc storage(size); 407 if (stream->read(storage.get(), size) != size) { 408 return false; 409 } 410 411 SkReadBuffer buffer(storage.get(), size); 412 buffer.setFlags(pictInfoFlagsToReadBufferFlags(fInfo.fFlags)); 413 buffer.setVersion(fInfo.fVersion); 414 415 fFactoryPlayback->setupBuffer(buffer); 416 fTFPlayback.setupBuffer(buffer); 417 buffer.setBitmapDecoder(proc); 418 419 while (!buffer.eof()) { 420 tag = buffer.readUInt(); 421 size = buffer.readUInt(); 422 if (!this->parseBufferTag(buffer, tag, size)) { 423 return false; 424 } 425 } 426 SkDEBUGCODE(haveBuffer = true;) 427 } break; 428 } 429 return true; // success 430} 431 432bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, 433 uint32_t tag, uint32_t size) { 434 switch (tag) { 435 case SK_PICT_BITMAP_BUFFER_TAG: { 436 const int count = SkToInt(size); 437 fBitmaps = SkTRefArray<SkBitmap>::Create(size); 438 for (int i = 0; i < count; ++i) { 439 SkBitmap* bm = &fBitmaps->writableAt(i); 440 buffer.readBitmap(bm); 441 bm->setImmutable(); 442 } 443 } break; 444 case SK_PICT_PAINT_BUFFER_TAG: { 445 const int count = SkToInt(size); 446 fPaints = SkTRefArray<SkPaint>::Create(size); 447 for (int i = 0; i < count; ++i) { 448 buffer.readPaint(&fPaints->writableAt(i)); 449 } 450 } break; 451 case SK_PICT_PATH_BUFFER_TAG: 452 if (size > 0) { 453 fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer))); 454 } 455 break; 456 case SK_PICT_TEXTBLOB_BUFFER_TAG: { 457 if (!buffer.validate((0 == fTextBlobCount) && (NULL == fTextBlobRefs))) { 458 return false; 459 } 460 fTextBlobCount = size; 461 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount); 462 bool success = true; 463 int i = 0; 464 for ( ; i < fTextBlobCount; i++) { 465 fTextBlobRefs[i] = SkTextBlob::CreateFromBuffer(buffer); 466 if (NULL == fTextBlobRefs[i]) { 467 success = false; 468 break; 469 } 470 } 471 if (!success) { 472 // Delete all of the blobs that were already created (up to but excluding i): 473 for (int j = 0; j < i; j++) { 474 fTextBlobRefs[j]->unref(); 475 } 476 // Delete the array 477 SkDELETE_ARRAY(fTextBlobRefs); 478 fTextBlobRefs = NULL; 479 fTextBlobCount = 0; 480 return false; 481 } 482 } break; 483 case SK_PICT_READER_TAG: { 484 SkAutoDataUnref data(SkData::NewUninitialized(size)); 485 if (!buffer.readByteArray(data->writable_data(), size) || 486 !buffer.validate(NULL == fOpData)) { 487 return false; 488 } 489 SkASSERT(NULL == fOpData); 490 fOpData = data.detach(); 491 } break; 492 case SK_PICT_PICTURE_TAG: { 493 if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs))) { 494 return false; 495 } 496 fPictureCount = size; 497 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount); 498 bool success = true; 499 int i = 0; 500 for ( ; i < fPictureCount; i++) { 501 fPictureRefs[i] = SkPicture::CreateFromBuffer(buffer); 502 if (NULL == fPictureRefs[i]) { 503 success = false; 504 break; 505 } 506 } 507 if (!success) { 508 // Delete all of the pictures that were already created (up to but excluding i): 509 for (int j = 0; j < i; j++) { 510 fPictureRefs[j]->unref(); 511 } 512 // Delete the array 513 SkDELETE_ARRAY(fPictureRefs); 514 fPictureCount = 0; 515 return false; 516 } 517 } break; 518 default: 519 // The tag was invalid. 520 return false; 521 } 522 return true; // success 523} 524 525SkPictureData* SkPictureData::CreateFromStream(SkStream* stream, 526 const SkPictInfo& info, 527 SkPicture::InstallPixelRefProc proc) { 528 SkAutoTDelete<SkPictureData> data(SkNEW_ARGS(SkPictureData, (info))); 529 530 if (!data->parseStream(stream, proc)) { 531 return NULL; 532 } 533 return data.detach(); 534} 535 536SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer, 537 const SkPictInfo& info) { 538 SkAutoTDelete<SkPictureData> data(SkNEW_ARGS(SkPictureData, (info))); 539 buffer.setVersion(info.fVersion); 540 541 if (!data->parseBuffer(buffer)) { 542 return NULL; 543 } 544 return data.detach(); 545} 546 547bool SkPictureData::parseStream(SkStream* stream, 548 SkPicture::InstallPixelRefProc proc) { 549 for (;;) { 550 uint32_t tag = stream->readU32(); 551 if (SK_PICT_EOF_TAG == tag) { 552 break; 553 } 554 555 uint32_t size = stream->readU32(); 556 if (!this->parseStreamTag(stream, tag, size, proc)) { 557 return false; // we're invalid 558 } 559 } 560 return true; 561} 562 563bool SkPictureData::parseBuffer(SkReadBuffer& buffer) { 564 for (;;) { 565 uint32_t tag = buffer.readUInt(); 566 if (SK_PICT_EOF_TAG == tag) { 567 break; 568 } 569 570 uint32_t size = buffer.readUInt(); 571 if (!this->parseBufferTag(buffer, tag, size)) { 572 return false; // we're invalid 573 } 574 } 575 return true; 576} 577 578/////////////////////////////////////////////////////////////////////////////// 579/////////////////////////////////////////////////////////////////////////////// 580 581const SkPicture::OperationList* SkPictureData::getActiveOps(const SkRect& query) const { 582 if (NULL == fStateTree || NULL == fBoundingHierarchy) { 583 return NULL; 584 } 585 586 SkPicture::OperationList* activeOps = SkNEW(SkPicture::OperationList); 587 fBoundingHierarchy->search(query, &(activeOps->fOps)); 588 return activeOps; 589} 590 591#if SK_SUPPORT_GPU 592bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason, 593 int sampleCount) const { 594 return fContentInfo.suitableForGpuRasterization(context, reason, sampleCount); 595} 596 597bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason, 598 GrPixelConfig config, SkScalar dpi) const { 599 600 if (context != NULL) { 601 return this->suitableForGpuRasterization(context, reason, 602 context->getRecommendedSampleCount(config, dpi)); 603 } else { 604 return this->suitableForGpuRasterization(NULL, reason); 605 } 606} 607 608bool SkPictureData::suitableForLayerOptimization() const { 609 return fContentInfo.numLayers() > 0; 610} 611#endif 612/////////////////////////////////////////////////////////////////////////////// 613 614 615