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