2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
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"
16 #include "SkWriteBuffer.h"
19 #include "GrContext.h"
22 template <typename T> int SafeCount(const T* obj) {
23 return obj ? obj->count() : 0;
26 SkPictureData::SkPictureData(const SkPictInfo& info)
31 void 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();
40 SkPictureData::SkPictureData(const SkPictureRecord& record,
41 const SkPictInfo& info,
47 fOpData = record.opData(deepCopyOps);
49 fBoundingHierarchy = record.fBoundingHierarchy;
50 fStateTree = record.fStateTree;
52 SkSafeRef(fBoundingHierarchy);
53 SkSafeRef(fStateTree);
54 fContentInfo.set(record.fContentInfo);
56 if (fBoundingHierarchy) {
57 fBoundingHierarchy->flushDeferredInserts();
60 // copy over the refcnt dictionary to our reader
61 record.fFlattenableHeap.setupPlaybacks();
63 fBitmaps = record.fBitmapHeap->extractBitmaps();
64 fPaints = record.fPaints.unflattenToArray();
66 fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap));
67 fPathHeap.reset(SkSafeRef(record.pathHeap()));
69 this->initForPlayback();
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();
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]);
92 #ifdef SK_SUPPORT_LEGACY_PICTURE_CLONE
93 SkPictureData::SkPictureData(const SkPictureData& src, SkPictCopyInfo* deepCopyInfo)
97 fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get()));
98 fPathHeap.reset(SkSafeRef(src.fPathHeap.get()));
100 fOpData = SkSafeRef(src.fOpData);
102 fBoundingHierarchy = src.fBoundingHierarchy;
103 fStateTree = src.fStateTree;
104 fContentInfo.set(src.fContentInfo);
106 SkSafeRef(fBoundingHierarchy);
107 SkSafeRef(fStateTree);
110 int paintCount = SafeCount(src.fPaints);
113 fBitmaps = SkTRefArray<SkBitmap>::Create(src.fBitmaps->begin(), src.fBitmaps->count());
116 fPaints = SkTRefArray<SkPaint>::Create(paintCount);
117 SkASSERT(deepCopyInfo->paintData.count() == paintCount);
118 SkBitmapHeap* bmHeap = deepCopyInfo->controller.getBitmapHeap();
119 SkTypefacePlayback* tfPlayback = deepCopyInfo->controller.getTypefacePlayback();
120 for (int i = 0; i < paintCount; i++) {
121 if (deepCopyInfo->paintData[i]) {
122 deepCopyInfo->paintData[i]->unflatten<SkPaint::FlatteningTraits>(
123 &fPaints->writableAt(i), bmHeap, tfPlayback);
125 // needs_deep_copy was false, so just need to assign
126 fPaints->writableAt(i) = src.fPaints->at(i);
131 fBitmaps = SkSafeRef(src.fBitmaps);
132 fPaints = SkSafeRef(src.fPaints);
135 fPictureCount = src.fPictureCount;
136 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
137 for (int i = 0; i < fPictureCount; i++) {
139 fPictureRefs[i] = src.fPictureRefs[i]->clone();
141 fPictureRefs[i] = src.fPictureRefs[i];
142 fPictureRefs[i]->ref();
146 #endif//SK_SUPPORT_LEGACY_PICTURE_CLONE
148 void SkPictureData::init() {
153 fTextBlobRefs = NULL;
156 fFactoryPlayback = NULL;
157 fBoundingHierarchy = NULL;
161 SkPictureData::~SkPictureData() {
162 SkSafeUnref(fOpData);
164 SkSafeUnref(fBitmaps);
165 SkSafeUnref(fPaints);
166 SkSafeUnref(fBoundingHierarchy);
167 SkSafeUnref(fStateTree);
169 for (int i = 0; i < fPictureCount; i++) {
170 fPictureRefs[i]->unref();
172 SkDELETE_ARRAY(fPictureRefs);
174 for (int i = 0; i < fTextBlobCount; i++) {
175 fTextBlobRefs[i]->unref();
177 SkDELETE_ARRAY(fTextBlobRefs);
179 SkDELETE(fFactoryPlayback);
182 bool SkPictureData::containsBitmaps() const {
183 if (fBitmaps && fBitmaps->count() > 0) {
186 for (int i = 0; i < fPictureCount; ++i) {
187 if (fPictureRefs[i]->willPlayBackBitmaps()) {
194 ///////////////////////////////////////////////////////////////////////////////
195 ///////////////////////////////////////////////////////////////////////////////
197 #include "SkStream.h"
199 static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
200 size_t size = 4; // for 'count'
202 for (int i = 0; i < count; i++) {
203 const char* name = SkFlattenable::FactoryToName(array[i]);
204 if (NULL == name || 0 == *name) {
205 size += SkWStream::SizeOfPackedUInt(0);
207 size_t len = strlen(name);
208 size += SkWStream::SizeOfPackedUInt(len);
216 static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, size_t size) {
217 buffer.writeUInt(tag);
218 buffer.writeUInt(SkToU32(size));
221 static void write_tag_size(SkWStream* stream, uint32_t tag, size_t size) {
222 stream->write32(tag);
223 stream->write32(SkToU32(size));
226 void SkPictureData::WriteFactories(SkWStream* stream, const SkFactorySet& rec) {
227 int count = rec.count();
229 SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
230 SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
231 rec.copyToArray(array);
233 size_t size = compute_chunk_size(array, count);
235 // TODO: write_tag_size should really take a size_t
236 write_tag_size(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
237 SkDEBUGCODE(size_t start = stream->bytesWritten());
238 stream->write32(count);
240 for (int i = 0; i < count; i++) {
241 const char* name = SkFlattenable::FactoryToName(array[i]);
242 if (NULL == name || 0 == *name) {
243 stream->writePackedUInt(0);
245 size_t len = strlen(name);
246 stream->writePackedUInt(len);
247 stream->write(name, len);
251 SkASSERT(size == (stream->bytesWritten() - start));
254 void SkPictureData::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
255 int count = rec.count();
257 write_tag_size(stream, SK_PICT_TYPEFACE_TAG, count);
259 SkAutoSTMalloc<16, SkTypeface*> storage(count);
260 SkTypeface** array = (SkTypeface**)storage.get();
261 rec.copyToArray((SkRefCnt**)array);
263 for (int i = 0; i < count; i++) {
264 array[i]->serialize(stream);
268 void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
271 if ((n = SafeCount(fBitmaps)) > 0) {
272 write_tag_size(buffer, SK_PICT_BITMAP_BUFFER_TAG, n);
273 for (i = 0; i < n; i++) {
274 buffer.writeBitmap((*fBitmaps)[i]);
278 if ((n = SafeCount(fPaints)) > 0) {
279 write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
280 for (i = 0; i < n; i++) {
281 buffer.writePaint((*fPaints)[i]);
285 if ((n = SafeCount(fPathHeap.get())) > 0) {
286 write_tag_size(buffer, SK_PICT_PATH_BUFFER_TAG, n);
287 fPathHeap->flatten(buffer);
290 if (fTextBlobCount > 0) {
291 write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobCount);
292 for (i = 0; i < fTextBlobCount; ++i) {
293 fTextBlobRefs[i]->flatten(buffer);
298 void SkPictureData::serialize(SkWStream* stream,
299 SkPicture::EncodeBitmap encoder) const {
300 write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size());
301 stream->write(fOpData->bytes(), fOpData->size());
303 if (fPictureCount > 0) {
304 write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
305 for (int i = 0; i < fPictureCount; i++) {
306 fPictureRefs[i]->serialize(stream, encoder);
310 // Write some of our data into a writebuffer, and then serialize that
313 SkRefCntSet typefaceSet;
314 SkFactorySet factSet;
316 SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag);
317 buffer.setTypefaceRecorder(&typefaceSet);
318 buffer.setFactoryRecorder(&factSet);
319 buffer.setBitmapEncoder(encoder);
321 this->flattenToBuffer(buffer);
323 // We have to write these two sets into the stream *before* we write
324 // the buffer, since parsing that buffer will require that we already
325 // have these sets available to use.
326 WriteFactories(stream, factSet);
327 WriteTypefaces(stream, typefaceSet);
329 write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
330 buffer.writeToStream(stream);
333 stream->write32(SK_PICT_EOF_TAG);
336 void SkPictureData::flatten(SkWriteBuffer& buffer) const {
337 write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size());
338 buffer.writeByteArray(fOpData->bytes(), fOpData->size());
340 if (fPictureCount > 0) {
341 write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictureCount);
342 for (int i = 0; i < fPictureCount; i++) {
343 fPictureRefs[i]->flatten(buffer);
347 // Write this picture playback's data into a writebuffer
348 this->flattenToBuffer(buffer);
349 buffer.write32(SK_PICT_EOF_TAG);
352 ///////////////////////////////////////////////////////////////////////////////
355 * Return the corresponding SkReadBuffer flags, given a set of
358 static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
359 static const struct {
363 { SkPictInfo::kCrossProcess_Flag, SkReadBuffer::kCrossProcess_Flag },
364 { SkPictInfo::kScalarIsFloat_Flag, SkReadBuffer::kScalarIsFloat_Flag },
365 { SkPictInfo::kPtrIs64Bit_Flag, SkReadBuffer::kPtrIs64Bit_Flag },
369 for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) {
370 if (pictInfoFlags & gSD[i].fSrc) {
371 rbMask |= gSD[i].fDst;
377 bool SkPictureData::parseStreamTag(SkStream* stream,
380 SkPicture::InstallPixelRefProc proc) {
382 * By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
383 * its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
384 * but if they are present, they need to have been seen before the buffer.
386 * We assert that if/when we see either of these, that we have not yet seen
387 * the buffer tag, because if we have, then its too-late to deal with the
388 * factories or typefaces.
390 SkDEBUGCODE(bool haveBuffer = false;)
393 case SK_PICT_READER_TAG:
394 SkASSERT(NULL == fOpData);
395 fOpData = SkData::NewFromStream(stream, size);
400 case SK_PICT_FACTORY_TAG: {
401 SkASSERT(!haveBuffer);
402 // Remove this code when v21 and below are no longer supported. At the
403 // same time add a new 'count' variable and use it rather then reusing 'size'.
404 #ifndef DISABLE_V21_COMPATIBILITY_CODE
405 if (fInfo.fVersion >= 22) {
406 // in v22 this tag's size represents the size of the chunk in bytes
407 // and the number of factory strings is written out separately
409 size = stream->readU32();
410 #ifndef DISABLE_V21_COMPATIBILITY_CODE
413 fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size));
414 for (size_t i = 0; i < size; i++) {
416 const size_t len = stream->readPackedUInt();
418 if (stream->read(str.writable_str(), len) != len) {
421 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
424 case SK_PICT_TYPEFACE_TAG: {
425 SkASSERT(!haveBuffer);
426 const int count = SkToInt(size);
427 fTFPlayback.setCount(count);
428 for (int i = 0; i < count; i++) {
429 SkAutoTUnref<SkTypeface> tf(SkTypeface::Deserialize(stream));
430 if (!tf.get()) { // failed to deserialize
431 // fTFPlayback asserts it never has a null, so we plop in
433 tf.reset(SkTypeface::RefDefault());
435 fTFPlayback.set(i, tf);
438 case SK_PICT_PICTURE_TAG: {
439 fPictureCount = size;
440 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
443 for ( ; i < fPictureCount; i++) {
444 fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc);
445 if (NULL == fPictureRefs[i]) {
451 // Delete all of the pictures that were already created (up to but excluding i):
452 for (int j = 0; j < i; j++) {
453 fPictureRefs[j]->unref();
456 SkDELETE_ARRAY(fPictureRefs);
461 case SK_PICT_BUFFER_SIZE_TAG: {
462 SkAutoMalloc storage(size);
463 if (stream->read(storage.get(), size) != size) {
467 SkReadBuffer buffer(storage.get(), size);
468 buffer.setFlags(pictInfoFlagsToReadBufferFlags(fInfo.fFlags));
469 buffer.setVersion(fInfo.fVersion);
471 fFactoryPlayback->setupBuffer(buffer);
472 fTFPlayback.setupBuffer(buffer);
473 buffer.setBitmapDecoder(proc);
475 while (!buffer.eof()) {
476 tag = buffer.readUInt();
477 size = buffer.readUInt();
478 if (!this->parseBufferTag(buffer, tag, size)) {
482 SkDEBUGCODE(haveBuffer = true;)
485 return true; // success
488 bool SkPictureData::parseBufferTag(SkReadBuffer& buffer,
489 uint32_t tag, uint32_t size) {
491 case SK_PICT_BITMAP_BUFFER_TAG: {
492 const int count = SkToInt(size);
493 fBitmaps = SkTRefArray<SkBitmap>::Create(size);
494 for (int i = 0; i < count; ++i) {
495 SkBitmap* bm = &fBitmaps->writableAt(i);
496 buffer.readBitmap(bm);
500 case SK_PICT_PAINT_BUFFER_TAG: {
501 const int count = SkToInt(size);
502 fPaints = SkTRefArray<SkPaint>::Create(size);
503 for (int i = 0; i < count; ++i) {
504 buffer.readPaint(&fPaints->writableAt(i));
507 case SK_PICT_PATH_BUFFER_TAG:
509 fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer)));
512 case SK_PICT_TEXTBLOB_BUFFER_TAG: {
513 if (!buffer.validate((0 == fTextBlobCount) && (NULL == fTextBlobRefs))) {
516 fTextBlobCount = size;
517 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount);
520 for ( ; i < fTextBlobCount; i++) {
521 fTextBlobRefs[i] = SkTextBlob::CreateFromBuffer(buffer);
522 if (NULL == fTextBlobRefs[i]) {
528 // Delete all of the blobs that were already created (up to but excluding i):
529 for (int j = 0; j < i; j++) {
530 fTextBlobRefs[j]->unref();
533 SkDELETE_ARRAY(fTextBlobRefs);
534 fTextBlobRefs = NULL;
539 case SK_PICT_READER_TAG: {
540 SkAutoDataUnref data(SkData::NewUninitialized(size));
541 if (!buffer.readByteArray(data->writable_data(), size) ||
542 !buffer.validate(NULL == fOpData)) {
545 SkASSERT(NULL == fOpData);
546 fOpData = data.detach();
548 case SK_PICT_PICTURE_TAG: {
549 if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs))) {
552 fPictureCount = size;
553 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
556 for ( ; i < fPictureCount; i++) {
557 fPictureRefs[i] = SkPicture::CreateFromBuffer(buffer);
558 if (NULL == fPictureRefs[i]) {
564 // Delete all of the pictures that were already created (up to but excluding i):
565 for (int j = 0; j < i; j++) {
566 fPictureRefs[j]->unref();
569 SkDELETE_ARRAY(fPictureRefs);
575 // The tag was invalid.
578 return true; // success
581 SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
582 const SkPictInfo& info,
583 SkPicture::InstallPixelRefProc proc) {
584 SkAutoTDelete<SkPictureData> data(SkNEW_ARGS(SkPictureData, (info)));
586 if (!data->parseStream(stream, proc)) {
589 return data.detach();
592 SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer,
593 const SkPictInfo& info) {
594 SkAutoTDelete<SkPictureData> data(SkNEW_ARGS(SkPictureData, (info)));
595 buffer.setVersion(info.fVersion);
597 if (!data->parseBuffer(buffer)) {
600 return data.detach();
603 bool SkPictureData::parseStream(SkStream* stream,
604 SkPicture::InstallPixelRefProc proc) {
606 uint32_t tag = stream->readU32();
607 if (SK_PICT_EOF_TAG == tag) {
611 uint32_t size = stream->readU32();
612 if (!this->parseStreamTag(stream, tag, size, proc)) {
613 return false; // we're invalid
619 bool SkPictureData::parseBuffer(SkReadBuffer& buffer) {
621 uint32_t tag = buffer.readUInt();
622 if (SK_PICT_EOF_TAG == tag) {
626 uint32_t size = buffer.readUInt();
627 if (!this->parseBufferTag(buffer, tag, size)) {
628 return false; // we're invalid
634 ///////////////////////////////////////////////////////////////////////////////
635 ///////////////////////////////////////////////////////////////////////////////
637 const SkPicture::OperationList* SkPictureData::getActiveOps(const SkRect& query) const {
638 if (NULL == fStateTree || NULL == fBoundingHierarchy) {
642 SkPicture::OperationList* activeOps = SkNEW(SkPicture::OperationList);
643 fBoundingHierarchy->search(query, &(activeOps->fOps));
648 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
649 int sampleCount) const {
650 return fContentInfo.suitableForGpuRasterization(context, reason, sampleCount);
653 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
654 GrPixelConfig config, SkScalar dpi) const {
656 if (context != NULL) {
657 return this->suitableForGpuRasterization(context, reason,
658 context->getRecommendedSampleCount(config, dpi));
660 return this->suitableForGpuRasterization(NULL, reason);
664 bool SkPictureData::suitableForLayerOptimization() const {
665 return fContentInfo.numLayers() > 0;
668 ///////////////////////////////////////////////////////////////////////////////