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
8 #include <new>
9
10 #include "SkAutoMalloc.h"
11 #include "SkImageGenerator.h"
12 #include "SkPictureData.h"
13 #include "SkPictureRecord.h"
14 #include "SkReadBuffer.h"
15 #include "SkTextBlob.h"
16 #include "SkTypeface.h"
17 #include "SkWriteBuffer.h"
18
19 #if SK_SUPPORT_GPU
20 #include "GrContext.h"
21 #endif
22
SafeCount(const T * obj)23 template <typename T> int SafeCount(const T* obj) {
24 return obj ? obj->count() : 0;
25 }
26
SkPictureData(const SkPictInfo & info)27 SkPictureData::SkPictureData(const SkPictInfo& info)
28 : fInfo(info) {
29 this->init();
30 }
31
initForPlayback() const32 void SkPictureData::initForPlayback() const {
33 // ensure that the paths bounds are pre-computed
34 for (int i = 0; i < fPaths.count(); i++) {
35 fPaths[i].updateBoundsCache();
36 }
37 }
38
SkPictureData(const SkPictureRecord & record,const SkPictInfo & info)39 SkPictureData::SkPictureData(const SkPictureRecord& record,
40 const SkPictInfo& info)
41 : fInfo(info) {
42
43 this->init();
44
45 fOpData = record.opData();
46
47 fContentInfo.set(record.fContentInfo);
48
49 fPaints = record.fPaints;
50
51 fPaths.reset(record.fPaths.count());
52 record.fPaths.foreach([this](const SkPath& path, int n) {
53 // These indices are logically 1-based, but we need to serialize them
54 // 0-based to keep the deserializing SkPictureData::getPath() working.
55 fPaths[n-1] = path;
56 });
57
58 this->initForPlayback();
59
60 const SkTDArray<const SkPicture* >& pictures = record.getPictureRefs();
61 fPictureCount = pictures.count();
62 if (fPictureCount > 0) {
63 fPictureRefs = new const SkPicture* [fPictureCount];
64 for (int i = 0; i < fPictureCount; i++) {
65 fPictureRefs[i] = pictures[i];
66 fPictureRefs[i]->ref();
67 }
68 }
69
70 const SkTDArray<SkDrawable* >& drawables = record.getDrawableRefs();
71 fDrawableCount = drawables.count();
72 if (fDrawableCount > 0) {
73 fDrawableRefs = new SkDrawable* [fDrawableCount];
74 for (int i = 0; i < fDrawableCount; i++) {
75 fDrawableRefs[i] = drawables[i];
76 fDrawableRefs[i]->ref();
77 }
78 }
79
80 // templatize to consolidate with similar picture logic?
81 const SkTDArray<const SkTextBlob*>& blobs = record.getTextBlobRefs();
82 fTextBlobCount = blobs.count();
83 if (fTextBlobCount > 0) {
84 fTextBlobRefs = new const SkTextBlob* [fTextBlobCount];
85 for (int i = 0; i < fTextBlobCount; ++i) {
86 fTextBlobRefs[i] = SkRef(blobs[i]);
87 }
88 }
89
90 const SkTDArray<const SkVertices*>& verts = record.getVerticesRefs();
91 fVerticesCount = verts.count();
92 if (fVerticesCount > 0) {
93 fVerticesRefs = new const SkVertices* [fVerticesCount];
94 for (int i = 0; i < fVerticesCount; ++i) {
95 fVerticesRefs[i] = SkRef(verts[i]);
96 }
97 }
98
99 const SkTDArray<const SkImage*>& imgs = record.getImageRefs();
100 fImageCount = imgs.count();
101 if (fImageCount > 0) {
102 fImageRefs = new const SkImage* [fImageCount];
103 for (int i = 0; i < fImageCount; ++i) {
104 fImageRefs[i] = SkRef(imgs[i]);
105 }
106 }
107 }
108
init()109 void SkPictureData::init() {
110 fPictureRefs = nullptr;
111 fPictureCount = 0;
112 fDrawableRefs = nullptr;
113 fDrawableCount = 0;
114 fTextBlobRefs = nullptr;
115 fTextBlobCount = 0;
116 fVerticesRefs = nullptr;
117 fVerticesCount = 0;
118 fImageRefs = nullptr;
119 fImageCount = 0;
120 fFactoryPlayback = nullptr;
121 }
122
~SkPictureData()123 SkPictureData::~SkPictureData() {
124 for (int i = 0; i < fPictureCount; i++) {
125 fPictureRefs[i]->unref();
126 }
127 delete[] fPictureRefs;
128
129 for (int i = 0; i < fDrawableCount; i++) {
130 fDrawableRefs[i]->unref();
131 }
132 if (fDrawableCount > 0) {
133 SkASSERT(fDrawableRefs);
134 delete[] fDrawableRefs;
135 }
136
137 for (int i = 0; i < fTextBlobCount; i++) {
138 fTextBlobRefs[i]->unref();
139 }
140 delete[] fTextBlobRefs;
141
142 for (int i = 0; i < fVerticesCount; i++) {
143 fVerticesRefs[i]->unref();
144 }
145 delete[] fVerticesRefs;
146
147 for (int i = 0; i < fImageCount; i++) {
148 fImageRefs[i]->unref();
149 }
150 delete[] fImageRefs;
151
152 delete fFactoryPlayback;
153 }
154
containsBitmaps() const155 bool SkPictureData::containsBitmaps() const {
156 if (fBitmapImageCount > 0 || fImageCount > 0) {
157 return true;
158 }
159 for (int i = 0; i < fPictureCount; ++i) {
160 if (fPictureRefs[i]->willPlayBackBitmaps()) {
161 return true;
162 }
163 }
164 return false;
165 }
166
167 ///////////////////////////////////////////////////////////////////////////////
168 ///////////////////////////////////////////////////////////////////////////////
169
170 #include "SkStream.h"
171
compute_chunk_size(SkFlattenable::Factory * array,int count)172 static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
173 size_t size = 4; // for 'count'
174
175 for (int i = 0; i < count; i++) {
176 const char* name = SkFlattenable::FactoryToName(array[i]);
177 if (nullptr == name || 0 == *name) {
178 size += SkWStream::SizeOfPackedUInt(0);
179 } else {
180 size_t len = strlen(name);
181 size += SkWStream::SizeOfPackedUInt(len);
182 size += len;
183 }
184 }
185
186 return size;
187 }
188
write_tag_size(SkWriteBuffer & buffer,uint32_t tag,size_t size)189 static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, size_t size) {
190 buffer.writeUInt(tag);
191 buffer.writeUInt(SkToU32(size));
192 }
193
write_tag_size(SkWStream * stream,uint32_t tag,size_t size)194 static void write_tag_size(SkWStream* stream, uint32_t tag, size_t size) {
195 stream->write32(tag);
196 stream->write32(SkToU32(size));
197 }
198
WriteFactories(SkWStream * stream,const SkFactorySet & rec)199 void SkPictureData::WriteFactories(SkWStream* stream, const SkFactorySet& rec) {
200 int count = rec.count();
201
202 SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
203 SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
204 rec.copyToArray(array);
205
206 size_t size = compute_chunk_size(array, count);
207
208 // TODO: write_tag_size should really take a size_t
209 write_tag_size(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
210 SkDEBUGCODE(size_t start = stream->bytesWritten());
211 stream->write32(count);
212
213 for (int i = 0; i < count; i++) {
214 const char* name = SkFlattenable::FactoryToName(array[i]);
215 if (nullptr == name || 0 == *name) {
216 stream->writePackedUInt(0);
217 } else {
218 size_t len = strlen(name);
219 stream->writePackedUInt(len);
220 stream->write(name, len);
221 }
222 }
223
224 SkASSERT(size == (stream->bytesWritten() - start));
225 }
226
WriteTypefaces(SkWStream * stream,const SkRefCntSet & rec)227 void SkPictureData::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
228 int count = rec.count();
229
230 write_tag_size(stream, SK_PICT_TYPEFACE_TAG, count);
231
232 SkAutoSTMalloc<16, SkTypeface*> storage(count);
233 SkTypeface** array = (SkTypeface**)storage.get();
234 rec.copyToArray((SkRefCnt**)array);
235
236 for (int i = 0; i < count; i++) {
237 array[i]->serialize(stream);
238 }
239 }
240
flattenToBuffer(SkWriteBuffer & buffer) const241 void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
242 int i, n;
243
244 if ((n = fPaints.count()) > 0) {
245 write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
246 for (i = 0; i < n; i++) {
247 buffer.writePaint(fPaints[i]);
248 }
249 }
250
251 if ((n = fPaths.count()) > 0) {
252 write_tag_size(buffer, SK_PICT_PATH_BUFFER_TAG, n);
253 buffer.writeInt(n);
254 for (int i = 0; i < n; i++) {
255 buffer.writePath(fPaths[i]);
256 }
257 }
258
259 if (fTextBlobCount > 0) {
260 write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobCount);
261 for (i = 0; i < fTextBlobCount; ++i) {
262 fTextBlobRefs[i]->flatten(buffer);
263 }
264 }
265
266 if (fVerticesCount > 0) {
267 write_tag_size(buffer, SK_PICT_VERTICES_BUFFER_TAG, fVerticesCount);
268 for (i = 0; i < fVerticesCount; ++i) {
269 buffer.writeDataAsByteArray(fVerticesRefs[i]->encode().get());
270 }
271 }
272
273 if (fImageCount > 0) {
274 write_tag_size(buffer, SK_PICT_IMAGE_BUFFER_TAG, fImageCount);
275 for (i = 0; i < fImageCount; ++i) {
276 buffer.writeImage(fImageRefs[i]);
277 }
278 }
279 }
280
serialize(SkWStream * stream,SkPixelSerializer * pixelSerializer,SkRefCntSet * topLevelTypeFaceSet) const281 void SkPictureData::serialize(SkWStream* stream,
282 SkPixelSerializer* pixelSerializer,
283 SkRefCntSet* topLevelTypeFaceSet) const {
284 // This can happen at pretty much any time, so might as well do it first.
285 write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size());
286 stream->write(fOpData->bytes(), fOpData->size());
287
288 // We serialize all typefaces into the typeface section of the top-level picture.
289 SkRefCntSet localTypefaceSet;
290 SkRefCntSet* typefaceSet = topLevelTypeFaceSet ? topLevelTypeFaceSet : &localTypefaceSet;
291
292 // We delay serializing the bulk of our data until after we've serialized
293 // factories and typefaces by first serializing to an in-memory write buffer.
294 SkFactorySet factSet; // buffer refs factSet, so factSet must come first.
295 SkBinaryWriteBuffer buffer(SkBinaryWriteBuffer::kCrossProcess_Flag);
296 buffer.setFactoryRecorder(&factSet);
297 buffer.setPixelSerializer(sk_ref_sp(pixelSerializer));
298 buffer.setTypefaceRecorder(typefaceSet);
299 this->flattenToBuffer(buffer);
300
301 // Dummy serialize our sub-pictures for the side effect of filling
302 // typefaceSet with typefaces from sub-pictures.
303 struct DevNull: public SkWStream {
304 DevNull() : fBytesWritten(0) {}
305 size_t fBytesWritten;
306 bool write(const void*, size_t size) override { fBytesWritten += size; return true; }
307 size_t bytesWritten() const override { return fBytesWritten; }
308 } devnull;
309 for (int i = 0; i < fPictureCount; i++) {
310 fPictureRefs[i]->serialize(&devnull, pixelSerializer, typefaceSet);
311 }
312
313 // We need to write factories before we write the buffer.
314 // We need to write typefaces before we write the buffer or any sub-picture.
315 WriteFactories(stream, factSet);
316 if (typefaceSet == &localTypefaceSet) {
317 WriteTypefaces(stream, *typefaceSet);
318 }
319
320 // Write the buffer.
321 write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
322 buffer.writeToStream(stream);
323
324 // Write sub-pictures by calling serialize again.
325 if (fPictureCount > 0) {
326 write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
327 for (int i = 0; i < fPictureCount; i++) {
328 fPictureRefs[i]->serialize(stream, pixelSerializer, typefaceSet);
329 }
330 }
331
332 stream->write32(SK_PICT_EOF_TAG);
333 }
334
flatten(SkWriteBuffer & buffer) const335 void SkPictureData::flatten(SkWriteBuffer& buffer) const {
336 write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size());
337 buffer.writeByteArray(fOpData->bytes(), fOpData->size());
338
339 if (fPictureCount > 0) {
340 write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictureCount);
341 for (int i = 0; i < fPictureCount; i++) {
342 fPictureRefs[i]->flatten(buffer);
343 }
344 }
345
346 if (fDrawableCount > 0) {
347 write_tag_size(buffer, SK_PICT_DRAWABLE_TAG, fDrawableCount);
348 for (int i = 0; i < fDrawableCount; i++) {
349 buffer.writeFlattenable(fDrawableRefs[i]);
350 }
351 }
352
353 // Write this picture playback's data into a writebuffer
354 this->flattenToBuffer(buffer);
355 buffer.write32(SK_PICT_EOF_TAG);
356 }
357
358 ///////////////////////////////////////////////////////////////////////////////
359
360 /**
361 * Return the corresponding SkReadBuffer flags, given a set of
362 * SkPictInfo flags.
363 */
pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags)364 static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
365 static const struct {
366 uint32_t fSrc;
367 uint32_t fDst;
368 } gSD[] = {
369 { SkPictInfo::kCrossProcess_Flag, SkReadBuffer::kCrossProcess_Flag },
370 { SkPictInfo::kScalarIsFloat_Flag, SkReadBuffer::kScalarIsFloat_Flag },
371 { SkPictInfo::kPtrIs64Bit_Flag, SkReadBuffer::kPtrIs64Bit_Flag },
372 };
373
374 uint32_t rbMask = 0;
375 for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) {
376 if (pictInfoFlags & gSD[i].fSrc) {
377 rbMask |= gSD[i].fDst;
378 }
379 }
380 return rbMask;
381 }
382
parseStreamTag(SkStream * stream,uint32_t tag,uint32_t size,SkImageDeserializer * factory,SkTypefacePlayback * topLevelTFPlayback)383 bool SkPictureData::parseStreamTag(SkStream* stream,
384 uint32_t tag,
385 uint32_t size,
386 SkImageDeserializer* factory,
387 SkTypefacePlayback* topLevelTFPlayback) {
388 /*
389 * By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
390 * its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
391 * but if they are present, they need to have been seen before the buffer.
392 *
393 * We assert that if/when we see either of these, that we have not yet seen
394 * the buffer tag, because if we have, then its too-late to deal with the
395 * factories or typefaces.
396 */
397 SkDEBUGCODE(bool haveBuffer = false;)
398
399 switch (tag) {
400 case SK_PICT_READER_TAG:
401 SkASSERT(nullptr == fOpData);
402 fOpData = SkData::MakeFromStream(stream, size);
403 if (!fOpData) {
404 return false;
405 }
406 break;
407 case SK_PICT_FACTORY_TAG: {
408 SkASSERT(!haveBuffer);
409 size = stream->readU32();
410 fFactoryPlayback = new SkFactoryPlayback(size);
411 for (size_t i = 0; i < size; i++) {
412 SkString str;
413 const size_t len = stream->readPackedUInt();
414 str.resize(len);
415 if (stream->read(str.writable_str(), len) != len) {
416 return false;
417 }
418 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
419 }
420 } break;
421 case SK_PICT_TYPEFACE_TAG: {
422 SkASSERT(!haveBuffer);
423 const int count = SkToInt(size);
424 fTFPlayback.setCount(count);
425 for (int i = 0; i < count; i++) {
426 sk_sp<SkTypeface> tf(SkTypeface::MakeDeserialize(stream));
427 if (!tf.get()) { // failed to deserialize
428 // fTFPlayback asserts it never has a null, so we plop in
429 // the default here.
430 tf = SkTypeface::MakeDefault();
431 }
432 fTFPlayback.set(i, tf.get());
433 }
434 } break;
435 case SK_PICT_PICTURE_TAG: {
436 fPictureCount = 0;
437 fPictureRefs = new const SkPicture* [size];
438 for (uint32_t i = 0; i < size; i++) {
439 fPictureRefs[i] = SkPicture::MakeFromStream(stream, factory, topLevelTFPlayback).release();
440 if (!fPictureRefs[i]) {
441 return false;
442 }
443 fPictureCount++;
444 }
445 } break;
446 case SK_PICT_BUFFER_SIZE_TAG: {
447 SkAutoMalloc storage(size);
448 if (stream->read(storage.get(), size) != size) {
449 return false;
450 }
451
452 /* Should we use SkValidatingReadBuffer instead? */
453 SkReadBuffer buffer(storage.get(), size);
454 buffer.setFlags(pictInfoFlagsToReadBufferFlags(fInfo.fFlags));
455 buffer.setVersion(fInfo.getVersion());
456
457 if (!fFactoryPlayback) {
458 return false;
459 }
460 fFactoryPlayback->setupBuffer(buffer);
461 buffer.setImageDeserializer(factory);
462
463 if (fTFPlayback.count() > 0) {
464 // .skp files <= v43 have typefaces serialized with each sub picture.
465 fTFPlayback.setupBuffer(buffer);
466 } else {
467 // Newer .skp files serialize all typefaces with the top picture.
468 topLevelTFPlayback->setupBuffer(buffer);
469 }
470
471 while (!buffer.eof() && buffer.isValid()) {
472 tag = buffer.readUInt();
473 size = buffer.readUInt();
474 if (!this->parseBufferTag(buffer, tag, size)) {
475 return false;
476 }
477 }
478 if (!buffer.isValid()) {
479 return false;
480 }
481 SkDEBUGCODE(haveBuffer = true;)
482 } break;
483 }
484 return true; // success
485 }
486
create_image_from_buffer(SkReadBuffer & buffer)487 static const SkImage* create_image_from_buffer(SkReadBuffer& buffer) {
488 return buffer.readImage().release();
489 }
create_vertices_from_buffer(SkReadBuffer & buffer)490 static const SkVertices* create_vertices_from_buffer(SkReadBuffer& buffer) {
491 auto data = buffer.readByteArrayAsData();
492 return data ? SkVertices::Decode(data->data(), data->size()).release() : nullptr;
493 }
494
create_bitmap_image_from_buffer(SkReadBuffer & buffer)495 static const SkImage* create_bitmap_image_from_buffer(SkReadBuffer& buffer) {
496 return buffer.readBitmapAsImage().release();
497 }
498
499 // Need a shallow wrapper to return const SkPicture* to match the other factories,
500 // as SkPicture::CreateFromBuffer() returns SkPicture*
create_picture_from_buffer(SkReadBuffer & buffer)501 static const SkPicture* create_picture_from_buffer(SkReadBuffer& buffer) {
502 return SkPicture::MakeFromBuffer(buffer).release();
503 }
504
create_drawable_from_buffer(SkReadBuffer & buffer)505 static const SkDrawable* create_drawable_from_buffer(SkReadBuffer& buffer) {
506 return (SkDrawable*) buffer.readFlattenable(SkFlattenable::kSkDrawable_Type);
507 }
508
509 template <typename T>
new_array_from_buffer(SkReadBuffer & buffer,uint32_t inCount,const T *** array,int * outCount,const T * (* factory)(SkReadBuffer &))510 bool new_array_from_buffer(SkReadBuffer& buffer, uint32_t inCount,
511 const T*** array, int* outCount, const T* (*factory)(SkReadBuffer&)) {
512 if (!buffer.validate((0 == *outCount) && (nullptr == *array))) {
513 return false;
514 }
515 if (0 == inCount) {
516 return true;
517 }
518 if (!buffer.validate(SkTFitsIn<int>(inCount))) {
519 return false;
520 }
521
522 *outCount = inCount;
523 *array = new const T* [*outCount];
524 bool success = true;
525 int i = 0;
526 for (; i < *outCount; i++) {
527 (*array)[i] = factory(buffer);
528 if (nullptr == (*array)[i]) {
529 success = false;
530 break;
531 }
532 }
533 if (!success) {
534 // Delete all of the blobs that were already created (up to but excluding i):
535 for (int j = 0; j < i; j++) {
536 (*array)[j]->unref();
537 }
538 // Delete the array
539 delete[] * array;
540 *array = nullptr;
541 *outCount = 0;
542 return false;
543 }
544 return true;
545 }
546
parseBufferTag(SkReadBuffer & buffer,uint32_t tag,uint32_t size)547 bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t size) {
548 switch (tag) {
549 case SK_PICT_BITMAP_BUFFER_TAG:
550 if (!new_array_from_buffer(buffer, size, &fBitmapImageRefs, &fBitmapImageCount,
551 create_bitmap_image_from_buffer)) {
552 return false;
553 }
554 break;
555 case SK_PICT_PAINT_BUFFER_TAG: {
556 if (!buffer.validate(SkTFitsIn<int>(size))) {
557 return false;
558 }
559 const int count = SkToInt(size);
560 fPaints.reset(count);
561 for (int i = 0; i < count; ++i) {
562 buffer.readPaint(&fPaints[i]);
563 }
564 } break;
565 case SK_PICT_PATH_BUFFER_TAG:
566 if (size > 0) {
567 const int count = buffer.readInt();
568 fPaths.reset(count);
569 for (int i = 0; i < count; i++) {
570 buffer.readPath(&fPaths[i]);
571 }
572 } break;
573 case SK_PICT_TEXTBLOB_BUFFER_TAG:
574 if (!new_array_from_buffer(buffer, size, &fTextBlobRefs, &fTextBlobCount,
575 SkTextBlob::CreateFromBuffer)) {
576 return false;
577 }
578 break;
579 case SK_PICT_VERTICES_BUFFER_TAG:
580 if (!new_array_from_buffer(buffer, size, &fVerticesRefs, &fVerticesCount,
581 create_vertices_from_buffer)) {
582 return false;
583 }
584 break;
585 case SK_PICT_IMAGE_BUFFER_TAG:
586 if (!new_array_from_buffer(buffer, size, &fImageRefs, &fImageCount,
587 create_image_from_buffer)) {
588 return false;
589 }
590 break;
591 case SK_PICT_READER_TAG: {
592 auto data(SkData::MakeUninitialized(size));
593 if (!buffer.readByteArray(data->writable_data(), size) ||
594 !buffer.validate(nullptr == fOpData)) {
595 return false;
596 }
597 SkASSERT(nullptr == fOpData);
598 fOpData = std::move(data);
599 } break;
600 case SK_PICT_PICTURE_TAG:
601 if (!new_array_from_buffer(buffer, size, &fPictureRefs, &fPictureCount,
602 create_picture_from_buffer)) {
603 return false;
604 }
605 break;
606 case SK_PICT_DRAWABLE_TAG:
607 if (!new_array_from_buffer(buffer, size, (const SkDrawable***)&fDrawableRefs,
608 &fDrawableCount, create_drawable_from_buffer)) {
609 return false;
610 }
611 break;
612 default:
613 // The tag was invalid.
614 return false;
615 }
616 return true; // success
617 }
618
CreateFromStream(SkStream * stream,const SkPictInfo & info,SkImageDeserializer * factory,SkTypefacePlayback * topLevelTFPlayback)619 SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
620 const SkPictInfo& info,
621 SkImageDeserializer* factory,
622 SkTypefacePlayback* topLevelTFPlayback) {
623 std::unique_ptr<SkPictureData> data(new SkPictureData(info));
624 if (!topLevelTFPlayback) {
625 topLevelTFPlayback = &data->fTFPlayback;
626 }
627
628 if (!data->parseStream(stream, factory, topLevelTFPlayback)) {
629 return nullptr;
630 }
631 return data.release();
632 }
633
CreateFromBuffer(SkReadBuffer & buffer,const SkPictInfo & info)634 SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer,
635 const SkPictInfo& info) {
636 std::unique_ptr<SkPictureData> data(new SkPictureData(info));
637 buffer.setVersion(info.getVersion());
638
639 if (!data->parseBuffer(buffer)) {
640 return nullptr;
641 }
642 return data.release();
643 }
644
parseStream(SkStream * stream,SkImageDeserializer * factory,SkTypefacePlayback * topLevelTFPlayback)645 bool SkPictureData::parseStream(SkStream* stream,
646 SkImageDeserializer* factory,
647 SkTypefacePlayback* topLevelTFPlayback) {
648 for (;;) {
649 uint32_t tag = stream->readU32();
650 if (SK_PICT_EOF_TAG == tag) {
651 break;
652 }
653
654 uint32_t size = stream->readU32();
655 if (!this->parseStreamTag(stream, tag, size, factory, topLevelTFPlayback)) {
656 return false; // we're invalid
657 }
658 }
659 return true;
660 }
661
parseBuffer(SkReadBuffer & buffer)662 bool SkPictureData::parseBuffer(SkReadBuffer& buffer) {
663 for (;;) {
664 uint32_t tag = buffer.readUInt();
665 if (SK_PICT_EOF_TAG == tag) {
666 break;
667 }
668
669 uint32_t size = buffer.readUInt();
670 if (!this->parseBufferTag(buffer, tag, size)) {
671 return false; // we're invalid
672 }
673 }
674 return true;
675 }
676
677 ///////////////////////////////////////////////////////////////////////////////
678 ///////////////////////////////////////////////////////////////////////////////
679
680 #if SK_SUPPORT_GPU
suitableForGpuRasterization(GrContext * context,const char ** reason,int sampleCount) const681 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
682 int sampleCount) const {
683 return fContentInfo.suitableForGpuRasterization(context, reason, sampleCount);
684 }
685
suitableForGpuRasterization(GrContext * context,const char ** reason,GrPixelConfig config,SkScalar dpi) const686 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
687 GrPixelConfig config, SkScalar dpi) const {
688
689 if (context != nullptr) {
690 return this->suitableForGpuRasterization(context, reason,
691 context->getRecommendedSampleCount(config, dpi));
692 } else {
693 return this->suitableForGpuRasterization(nullptr, reason);
694 }
695 }
696
suitableForLayerOptimization() const697 bool SkPictureData::suitableForLayerOptimization() const {
698 return fContentInfo.numLayers() > 0;
699 }
700 #endif
701 ///////////////////////////////////////////////////////////////////////////////
702