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