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 fContentInfo.set(record.fContentInfo);
51 // copy over the refcnt dictionary to our reader
52 record.fFlattenableHeap.setupPlaybacks();
54 fBitmaps = record.fBitmapHeap->extractBitmaps();
55 fPaints = record.fPaints.unflattenToArray();
57 fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap));
58 fPathHeap.reset(SkSafeRef(record.pathHeap()));
60 this->initForPlayback();
62 const SkTDArray<const SkPicture* >& pictures = record.getPictureRefs();
63 fPictureCount = pictures.count();
64 if (fPictureCount > 0) {
65 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
66 for (int i = 0; i < fPictureCount; i++) {
67 fPictureRefs[i] = pictures[i];
68 fPictureRefs[i]->ref();
72 // templatize to consolidate with similar picture logic?
73 const SkTDArray<const SkTextBlob*>& blobs = record.getTextBlobRefs();
74 fTextBlobCount = blobs.count();
75 if (fTextBlobCount > 0) {
76 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount);
77 for (int i = 0; i < fTextBlobCount; ++i) {
78 fTextBlobRefs[i] = SkRef(blobs[i]);
83 void SkPictureData::init() {
91 fFactoryPlayback = NULL;
94 SkPictureData::~SkPictureData() {
97 SkSafeUnref(fBitmaps);
100 for (int i = 0; i < fPictureCount; i++) {
101 fPictureRefs[i]->unref();
103 SkDELETE_ARRAY(fPictureRefs);
105 for (int i = 0; i < fTextBlobCount; i++) {
106 fTextBlobRefs[i]->unref();
108 SkDELETE_ARRAY(fTextBlobRefs);
110 SkDELETE(fFactoryPlayback);
113 bool SkPictureData::containsBitmaps() const {
114 if (fBitmaps && fBitmaps->count() > 0) {
117 for (int i = 0; i < fPictureCount; ++i) {
118 if (fPictureRefs[i]->willPlayBackBitmaps()) {
125 ///////////////////////////////////////////////////////////////////////////////
126 ///////////////////////////////////////////////////////////////////////////////
128 #include "SkStream.h"
130 static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
131 size_t size = 4; // for 'count'
133 for (int i = 0; i < count; i++) {
134 const char* name = SkFlattenable::FactoryToName(array[i]);
135 if (NULL == name || 0 == *name) {
136 size += SkWStream::SizeOfPackedUInt(0);
138 size_t len = strlen(name);
139 size += SkWStream::SizeOfPackedUInt(len);
147 static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, size_t size) {
148 buffer.writeUInt(tag);
149 buffer.writeUInt(SkToU32(size));
152 static void write_tag_size(SkWStream* stream, uint32_t tag, size_t size) {
153 stream->write32(tag);
154 stream->write32(SkToU32(size));
157 void SkPictureData::WriteFactories(SkWStream* stream, const SkFactorySet& rec) {
158 int count = rec.count();
160 SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
161 SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
162 rec.copyToArray(array);
164 size_t size = compute_chunk_size(array, count);
166 // TODO: write_tag_size should really take a size_t
167 write_tag_size(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
168 SkDEBUGCODE(size_t start = stream->bytesWritten());
169 stream->write32(count);
171 for (int i = 0; i < count; i++) {
172 const char* name = SkFlattenable::FactoryToName(array[i]);
173 if (NULL == name || 0 == *name) {
174 stream->writePackedUInt(0);
176 size_t len = strlen(name);
177 stream->writePackedUInt(len);
178 stream->write(name, len);
182 SkASSERT(size == (stream->bytesWritten() - start));
185 void SkPictureData::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
186 int count = rec.count();
188 write_tag_size(stream, SK_PICT_TYPEFACE_TAG, count);
190 SkAutoSTMalloc<16, SkTypeface*> storage(count);
191 SkTypeface** array = (SkTypeface**)storage.get();
192 rec.copyToArray((SkRefCnt**)array);
194 for (int i = 0; i < count; i++) {
195 array[i]->serialize(stream);
199 void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
202 if ((n = SafeCount(fBitmaps)) > 0) {
203 write_tag_size(buffer, SK_PICT_BITMAP_BUFFER_TAG, n);
204 for (i = 0; i < n; i++) {
205 buffer.writeBitmap((*fBitmaps)[i]);
209 if ((n = SafeCount(fPaints)) > 0) {
210 write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
211 for (i = 0; i < n; i++) {
212 buffer.writePaint((*fPaints)[i]);
216 if ((n = SafeCount(fPathHeap.get())) > 0) {
217 write_tag_size(buffer, SK_PICT_PATH_BUFFER_TAG, n);
218 fPathHeap->flatten(buffer);
221 if (fTextBlobCount > 0) {
222 write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobCount);
223 for (i = 0; i < fTextBlobCount; ++i) {
224 fTextBlobRefs[i]->flatten(buffer);
229 void SkPictureData::serialize(SkWStream* stream,
230 SkPicture::EncodeBitmap encoder) const {
231 write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size());
232 stream->write(fOpData->bytes(), fOpData->size());
234 if (fPictureCount > 0) {
235 write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
236 for (int i = 0; i < fPictureCount; i++) {
237 fPictureRefs[i]->serialize(stream, encoder);
241 // Write some of our data into a writebuffer, and then serialize that
244 SkRefCntSet typefaceSet;
245 SkFactorySet factSet;
247 SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag);
248 buffer.setTypefaceRecorder(&typefaceSet);
249 buffer.setFactoryRecorder(&factSet);
250 buffer.setBitmapEncoder(encoder);
252 this->flattenToBuffer(buffer);
254 // We have to write these two sets into the stream *before* we write
255 // the buffer, since parsing that buffer will require that we already
256 // have these sets available to use.
257 WriteFactories(stream, factSet);
258 WriteTypefaces(stream, typefaceSet);
260 write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
261 buffer.writeToStream(stream);
264 stream->write32(SK_PICT_EOF_TAG);
267 void SkPictureData::flatten(SkWriteBuffer& buffer) const {
268 write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size());
269 buffer.writeByteArray(fOpData->bytes(), fOpData->size());
271 if (fPictureCount > 0) {
272 write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictureCount);
273 for (int i = 0; i < fPictureCount; i++) {
274 fPictureRefs[i]->flatten(buffer);
278 // Write this picture playback's data into a writebuffer
279 this->flattenToBuffer(buffer);
280 buffer.write32(SK_PICT_EOF_TAG);
283 ///////////////////////////////////////////////////////////////////////////////
286 * Return the corresponding SkReadBuffer flags, given a set of
289 static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
290 static const struct {
294 { SkPictInfo::kCrossProcess_Flag, SkReadBuffer::kCrossProcess_Flag },
295 { SkPictInfo::kScalarIsFloat_Flag, SkReadBuffer::kScalarIsFloat_Flag },
296 { SkPictInfo::kPtrIs64Bit_Flag, SkReadBuffer::kPtrIs64Bit_Flag },
300 for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) {
301 if (pictInfoFlags & gSD[i].fSrc) {
302 rbMask |= gSD[i].fDst;
308 bool SkPictureData::parseStreamTag(SkStream* stream,
311 SkPicture::InstallPixelRefProc proc) {
313 * By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
314 * its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
315 * but if they are present, they need to have been seen before the buffer.
317 * We assert that if/when we see either of these, that we have not yet seen
318 * the buffer tag, because if we have, then its too-late to deal with the
319 * factories or typefaces.
321 SkDEBUGCODE(bool haveBuffer = false;)
324 case SK_PICT_READER_TAG:
325 SkASSERT(NULL == fOpData);
326 fOpData = SkData::NewFromStream(stream, size);
331 case SK_PICT_FACTORY_TAG: {
332 SkASSERT(!haveBuffer);
333 // Remove this code when v21 and below are no longer supported. At the
334 // same time add a new 'count' variable and use it rather then reusing 'size'.
335 #ifndef DISABLE_V21_COMPATIBILITY_CODE
336 if (fInfo.fVersion >= 22) {
337 // in v22 this tag's size represents the size of the chunk in bytes
338 // and the number of factory strings is written out separately
340 size = stream->readU32();
341 #ifndef DISABLE_V21_COMPATIBILITY_CODE
344 fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size));
345 for (size_t i = 0; i < size; i++) {
347 const size_t len = stream->readPackedUInt();
349 if (stream->read(str.writable_str(), len) != len) {
352 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
355 case SK_PICT_TYPEFACE_TAG: {
356 SkASSERT(!haveBuffer);
357 const int count = SkToInt(size);
358 fTFPlayback.setCount(count);
359 for (int i = 0; i < count; i++) {
360 SkAutoTUnref<SkTypeface> tf(SkTypeface::Deserialize(stream));
361 if (!tf.get()) { // failed to deserialize
362 // fTFPlayback asserts it never has a null, so we plop in
364 tf.reset(SkTypeface::RefDefault());
366 fTFPlayback.set(i, tf);
369 case SK_PICT_PICTURE_TAG: {
370 fPictureCount = size;
371 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
374 for ( ; i < fPictureCount; i++) {
375 fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc);
376 if (NULL == fPictureRefs[i]) {
382 // Delete all of the pictures that were already created (up to but excluding i):
383 for (int j = 0; j < i; j++) {
384 fPictureRefs[j]->unref();
387 SkDELETE_ARRAY(fPictureRefs);
392 case SK_PICT_BUFFER_SIZE_TAG: {
393 SkAutoMalloc storage(size);
394 if (stream->read(storage.get(), size) != size) {
398 SkReadBuffer buffer(storage.get(), size);
399 buffer.setFlags(pictInfoFlagsToReadBufferFlags(fInfo.fFlags));
400 buffer.setVersion(fInfo.fVersion);
402 fFactoryPlayback->setupBuffer(buffer);
403 fTFPlayback.setupBuffer(buffer);
404 buffer.setBitmapDecoder(proc);
406 while (!buffer.eof()) {
407 tag = buffer.readUInt();
408 size = buffer.readUInt();
409 if (!this->parseBufferTag(buffer, tag, size)) {
413 SkDEBUGCODE(haveBuffer = true;)
416 return true; // success
419 bool SkPictureData::parseBufferTag(SkReadBuffer& buffer,
420 uint32_t tag, uint32_t size) {
422 case SK_PICT_BITMAP_BUFFER_TAG: {
423 const int count = SkToInt(size);
424 fBitmaps = SkTRefArray<SkBitmap>::Create(size);
425 for (int i = 0; i < count; ++i) {
426 SkBitmap* bm = &fBitmaps->writableAt(i);
427 buffer.readBitmap(bm);
431 case SK_PICT_PAINT_BUFFER_TAG: {
432 const int count = SkToInt(size);
433 fPaints = SkTRefArray<SkPaint>::Create(size);
434 for (int i = 0; i < count; ++i) {
435 buffer.readPaint(&fPaints->writableAt(i));
438 case SK_PICT_PATH_BUFFER_TAG:
440 fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer)));
443 case SK_PICT_TEXTBLOB_BUFFER_TAG: {
444 if (!buffer.validate((0 == fTextBlobCount) && (NULL == fTextBlobRefs))) {
447 fTextBlobCount = size;
448 fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount);
451 for ( ; i < fTextBlobCount; i++) {
452 fTextBlobRefs[i] = SkTextBlob::CreateFromBuffer(buffer);
453 if (NULL == fTextBlobRefs[i]) {
459 // Delete all of the blobs that were already created (up to but excluding i):
460 for (int j = 0; j < i; j++) {
461 fTextBlobRefs[j]->unref();
464 SkDELETE_ARRAY(fTextBlobRefs);
465 fTextBlobRefs = NULL;
470 case SK_PICT_READER_TAG: {
471 SkAutoDataUnref data(SkData::NewUninitialized(size));
472 if (!buffer.readByteArray(data->writable_data(), size) ||
473 !buffer.validate(NULL == fOpData)) {
476 SkASSERT(NULL == fOpData);
477 fOpData = data.detach();
479 case SK_PICT_PICTURE_TAG: {
480 if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs))) {
483 fPictureCount = size;
484 fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
487 for ( ; i < fPictureCount; i++) {
488 fPictureRefs[i] = SkPicture::CreateFromBuffer(buffer);
489 if (NULL == fPictureRefs[i]) {
495 // Delete all of the pictures that were already created (up to but excluding i):
496 for (int j = 0; j < i; j++) {
497 fPictureRefs[j]->unref();
500 SkDELETE_ARRAY(fPictureRefs);
506 // The tag was invalid.
509 return true; // success
512 SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
513 const SkPictInfo& info,
514 SkPicture::InstallPixelRefProc proc) {
515 SkAutoTDelete<SkPictureData> data(SkNEW_ARGS(SkPictureData, (info)));
517 if (!data->parseStream(stream, proc)) {
520 return data.detach();
523 SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer,
524 const SkPictInfo& info) {
525 SkAutoTDelete<SkPictureData> data(SkNEW_ARGS(SkPictureData, (info)));
526 buffer.setVersion(info.fVersion);
528 if (!data->parseBuffer(buffer)) {
531 return data.detach();
534 bool SkPictureData::parseStream(SkStream* stream,
535 SkPicture::InstallPixelRefProc proc) {
537 uint32_t tag = stream->readU32();
538 if (SK_PICT_EOF_TAG == tag) {
542 uint32_t size = stream->readU32();
543 if (!this->parseStreamTag(stream, tag, size, proc)) {
544 return false; // we're invalid
550 bool SkPictureData::parseBuffer(SkReadBuffer& buffer) {
552 uint32_t tag = buffer.readUInt();
553 if (SK_PICT_EOF_TAG == tag) {
557 uint32_t size = buffer.readUInt();
558 if (!this->parseBufferTag(buffer, tag, size)) {
559 return false; // we're invalid
565 ///////////////////////////////////////////////////////////////////////////////
566 ///////////////////////////////////////////////////////////////////////////////
569 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
570 int sampleCount) const {
571 return fContentInfo.suitableForGpuRasterization(context, reason, sampleCount);
574 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
575 GrPixelConfig config, SkScalar dpi) const {
577 if (context != NULL) {
578 return this->suitableForGpuRasterization(context, reason,
579 context->getRecommendedSampleCount(config, dpi));
581 return this->suitableForGpuRasterization(NULL, reason);
585 bool SkPictureData::suitableForLayerOptimization() const {
586 return fContentInfo.numLayers() > 0;
589 ///////////////////////////////////////////////////////////////////////////////