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