• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SafeCount(const T * obj)19 template <typename T> int SafeCount(const T* obj) {
20     return obj ? obj->count() : 0;
21 }
22 
SkPictureData(const SkPictInfo & info)23 SkPictureData::SkPictureData(const SkPictInfo& info)
24     : fInfo(info) {
25     this->init();
26 }
27 
initForPlayback() const28 void 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 
SkPictureData(const SkPictureRecord & record,const SkPictInfo & info,bool deepCopyOps)35 SkPictureData::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 
init()73 void SkPictureData::init() {
74     fPictureRefs = NULL;
75     fPictureCount = 0;
76     fTextBlobRefs = NULL;
77     fTextBlobCount = 0;
78     fOpData = NULL;
79     fFactoryPlayback = NULL;
80 }
81 
~SkPictureData()82 SkPictureData::~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 
containsBitmaps() const98 bool 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 
compute_chunk_size(SkFlattenable::Factory * array,int count)115 static 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 
write_tag_size(SkWriteBuffer & buffer,uint32_t tag,size_t size)132 static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, size_t size) {
133     buffer.writeUInt(tag);
134     buffer.writeUInt(SkToU32(size));
135 }
136 
write_tag_size(SkWStream * stream,uint32_t tag,size_t size)137 static void write_tag_size(SkWStream* stream, uint32_t tag, size_t size) {
138     stream->write32(tag);
139     stream->write32(SkToU32(size));
140 }
141 
WriteFactories(SkWStream * stream,const SkFactorySet & rec)142 void 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 
WriteTypefaces(SkWStream * stream,const SkRefCntSet & rec)170 void 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 
flattenToBuffer(SkWriteBuffer & buffer) const189 void 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 
serialize(SkWStream * stream,SkPixelSerializer * pixelSerializer) const222 void 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 
flatten(SkWriteBuffer & buffer) const260 void 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  */
pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags)282 static 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 
parseStreamTag(SkStream * stream,uint32_t tag,uint32_t size,SkPicture::InstallPixelRefProc proc)301 bool 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 
parseBufferTag(SkReadBuffer & buffer,uint32_t tag,uint32_t size)406 bool 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 
CreateFromStream(SkStream * stream,const SkPictInfo & info,SkPicture::InstallPixelRefProc proc)505 SkPictureData* 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 
CreateFromBuffer(SkReadBuffer & buffer,const SkPictInfo & info)516 SkPictureData* 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 
parseStream(SkStream * stream,SkPicture::InstallPixelRefProc proc)527 bool 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 
parseBuffer(SkReadBuffer & buffer)543 bool 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
suitableForGpuRasterization(GrContext * context,const char ** reason,int sampleCount) const562 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
563                                                 int sampleCount) const {
564     return fContentInfo.suitableForGpuRasterization(context, reason, sampleCount);
565 }
566 
suitableForGpuRasterization(GrContext * context,const char ** reason,GrPixelConfig config,SkScalar dpi) const567 bool 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 
suitableForLayerOptimization() const578 bool SkPictureData::suitableForLayerOptimization() const {
579     return fContentInfo.numLayers() > 0;
580 }
581 #endif
582 ///////////////////////////////////////////////////////////////////////////////
583 
584 
585