• 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 
8 #include "src/core/SkPictureData.h"
9 
10 #include "include/core/SkFlattenable.h"
11 #include "include/core/SkSerialProcs.h"
12 #include "include/core/SkString.h"
13 #include "include/core/SkTypeface.h"
14 #include "include/private/base/SkDebug.h"
15 #include "include/private/base/SkTFitsIn.h"
16 #include "include/private/base/SkTemplates.h"
17 #include "include/private/base/SkTo.h"
18 #include "src/base/SkAutoMalloc.h"
19 #include "src/core/SkPicturePriv.h"
20 #include "src/core/SkPictureRecord.h"
21 #include "src/core/SkPtrRecorder.h"
22 #include "src/core/SkReadBuffer.h"
23 #include "src/core/SkStreamPriv.h"
24 #include "src/core/SkTHash.h"
25 #include "src/core/SkTextBlobPriv.h"
26 #include "src/core/SkVerticesPriv.h"
27 #include "src/core/SkWriteBuffer.h"
28 
29 #include <cstring>
30 #include <utility>
31 
32 #if defined(SK_GANESH)
33 #include "include/private/chromium/Slug.h"
34 #endif
35 
36 using namespace skia_private;
37 
SafeCount(const T * obj)38 template <typename T> int SafeCount(const T* obj) {
39     return obj ? obj->size() : 0;
40 }
41 
SkPictureData(const SkPictInfo & info)42 SkPictureData::SkPictureData(const SkPictInfo& info)
43     : fInfo(info) {}
44 
initForPlayback() const45 void SkPictureData::initForPlayback() const {
46     // ensure that the paths bounds are pre-computed
47     for (int i = 0; i < fPaths.size(); i++) {
48         fPaths[i].updateBoundsCache();
49     }
50 }
51 
SkPictureData(const SkPictureRecord & record,const SkPictInfo & info)52 SkPictureData::SkPictureData(const SkPictureRecord& record,
53                              const SkPictInfo& info)
54     : fPictures(record.getPictures())
55     , fDrawables(record.getDrawables())
56     , fTextBlobs(record.getTextBlobs())
57     , fVertices(record.getVertices())
58     , fImages(record.getImages())
59 #if defined(SK_GANESH)
60     , fSlugs(record.getSlugs())
61 #endif
62     , fInfo(info) {
63 
64     fOpData = record.opData();
65 
66     fPaints  = record.fPaints;
67 
68     fPaths.reset(record.fPaths.count());
69     record.fPaths.foreach([this](const SkPath& path, int n) {
70         // These indices are logically 1-based, but we need to serialize them
71         // 0-based to keep the deserializing SkPictureData::getPath() working.
72         fPaths[n-1] = path;
73     });
74 
75     this->initForPlayback();
76 }
77 
78 ///////////////////////////////////////////////////////////////////////////////
79 ///////////////////////////////////////////////////////////////////////////////
80 
81 #include "include/core/SkStream.h"
82 
compute_chunk_size(SkFlattenable::Factory * array,int count)83 static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
84     size_t size = 4;  // for 'count'
85 
86     for (int i = 0; i < count; i++) {
87         const char* name = SkFlattenable::FactoryToName(array[i]);
88         if (nullptr == name || 0 == *name) {
89             size += SkWStream::SizeOfPackedUInt(0);
90         } else {
91             size_t len = strlen(name);
92             size += SkWStream::SizeOfPackedUInt(len);
93             size += len;
94         }
95     }
96 
97     return size;
98 }
99 
write_tag_size(SkWriteBuffer & buffer,uint32_t tag,size_t size)100 static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, size_t size) {
101     buffer.writeUInt(tag);
102     buffer.writeUInt(SkToU32(size));
103 }
104 
write_tag_size(SkWStream * stream,uint32_t tag,size_t size)105 static void write_tag_size(SkWStream* stream, uint32_t tag, size_t size) {
106     stream->write32(tag);
107     stream->write32(SkToU32(size));
108 }
109 
WriteFactories(SkWStream * stream,const SkFactorySet & rec)110 void SkPictureData::WriteFactories(SkWStream* stream, const SkFactorySet& rec) {
111     int count = rec.count();
112 
113     AutoSTMalloc<16, SkFlattenable::Factory> storage(count);
114     SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
115     rec.copyToArray(array);
116 
117     size_t size = compute_chunk_size(array, count);
118 
119     // TODO: write_tag_size should really take a size_t
120     write_tag_size(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
121     SkDEBUGCODE(size_t start = stream->bytesWritten());
122     stream->write32(count);
123 
124     for (int i = 0; i < count; i++) {
125         const char* name = SkFlattenable::FactoryToName(array[i]);
126         if (nullptr == name || 0 == *name) {
127             stream->writePackedUInt(0);
128         } else {
129             size_t len = strlen(name);
130             stream->writePackedUInt(len);
131             stream->write(name, len);
132         }
133     }
134 
135     SkASSERT(size == (stream->bytesWritten() - start));
136 }
137 
WriteTypefaces(SkWStream * stream,const SkRefCntSet & rec,const SkSerialProcs & procs)138 void SkPictureData::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec,
139                                    const SkSerialProcs& procs) {
140     int count = rec.count();
141 
142     write_tag_size(stream, SK_PICT_TYPEFACE_TAG, count);
143 
144     AutoSTMalloc<16, SkTypeface*> storage(count);
145     SkTypeface** array = (SkTypeface**)storage.get();
146     rec.copyToArray((SkRefCnt**)array);
147 
148     for (int i = 0; i < count; i++) {
149         SkTypeface* tf = array[i];
150         if (procs.fTypefaceProc) {
151             auto data = procs.fTypefaceProc(tf, procs.fTypefaceCtx);
152             if (data) {
153                 stream->write(data->data(), data->size());
154                 continue;
155             }
156         }
157         array[i]->serialize(stream);
158     }
159 }
160 
flattenToBuffer(SkWriteBuffer & buffer,bool textBlobsOnly) const161 void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer, bool textBlobsOnly) const {
162     if (!textBlobsOnly) {
163         int numPaints = fPaints.size();
164         if (numPaints > 0) {
165             write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, numPaints);
166             for (const SkPaint& paint : fPaints) {
167                 buffer.writePaint(paint);
168             }
169         }
170 
171         int numPaths = fPaths.size();
172         if (numPaths > 0) {
173             write_tag_size(buffer, SK_PICT_PATH_BUFFER_TAG, numPaths);
174             buffer.writeInt(numPaths);
175             for (const SkPath& path : fPaths) {
176                 buffer.writePath(path);
177             }
178         }
179     }
180 
181     if (!fTextBlobs.empty()) {
182         write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobs.size());
183         for (const auto& blob : fTextBlobs) {
184             SkTextBlobPriv::Flatten(*blob, buffer);
185         }
186     }
187 
188 #if defined(SK_GANESH)
189     if (!textBlobsOnly) {
190         write_tag_size(buffer, SK_PICT_SLUG_BUFFER_TAG, fSlugs.size());
191         for (const auto& slug : fSlugs) {
192             slug->doFlatten(buffer);
193         }
194     }
195 #endif
196 
197     if (!textBlobsOnly) {
198         if (!fVertices.empty()) {
199             write_tag_size(buffer, SK_PICT_VERTICES_BUFFER_TAG, fVertices.size());
200             for (const auto& vert : fVertices) {
201                 vert->priv().encode(buffer);
202             }
203         }
204 
205         if (!fImages.empty()) {
206             write_tag_size(buffer, SK_PICT_IMAGE_BUFFER_TAG, fImages.size());
207             for (const auto& img : fImages) {
208                 buffer.writeImage(img.get());
209             }
210         }
211     }
212 }
213 
214 // SkPictureData::serialize() will write out paints, and then write out an array of typefaces
215 // (unique set). However, paint's serializer will respect SerialProcs, which can cause us to
216 // call that custom typefaceproc on *every* typeface, not just on the unique ones. To avoid this,
217 // we ignore the custom proc (here) when we serialize the paints, and then do respect it when
218 // we serialize the typefaces.
skip_typeface_proc(const SkSerialProcs & procs)219 static SkSerialProcs skip_typeface_proc(const SkSerialProcs& procs) {
220     SkSerialProcs newProcs = procs;
221     newProcs.fTypefaceProc = nullptr;
222     newProcs.fTypefaceCtx = nullptr;
223     return newProcs;
224 }
225 
226 // topLevelTypeFaceSet is null only on the top level call.
227 // This method is called recursively on every subpicture in two passes.
228 // textBlobsOnly serves to indicate that we are on the first pass and skip as much work as
229 // possible that is not relevant to collecting text blobs in topLevelTypeFaceSet
230 // TODO(nifong): dedupe typefaces and all other shared resources in a faster and more readable way.
serialize(SkWStream * stream,const SkSerialProcs & procs,SkRefCntSet * topLevelTypeFaceSet,bool textBlobsOnly) const231 void SkPictureData::serialize(SkWStream* stream, const SkSerialProcs& procs,
232                               SkRefCntSet* topLevelTypeFaceSet, bool textBlobsOnly) const {
233     // This can happen at pretty much any time, so might as well do it first.
234     write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size());
235     stream->write(fOpData->bytes(), fOpData->size());
236 
237     // We serialize all typefaces into the typeface section of the top-level picture.
238     SkRefCntSet localTypefaceSet;
239     SkRefCntSet* typefaceSet = topLevelTypeFaceSet ? topLevelTypeFaceSet : &localTypefaceSet;
240 
241     // We delay serializing the bulk of our data until after we've serialized
242     // factories and typefaces by first serializing to an in-memory write buffer.
243     SkFactorySet factSet;  // buffer refs factSet, so factSet must come first.
244     SkBinaryWriteBuffer buffer;
245     buffer.setFactoryRecorder(sk_ref_sp(&factSet));
246     buffer.setSerialProcs(skip_typeface_proc(procs));
247     buffer.setTypefaceRecorder(sk_ref_sp(typefaceSet));
248     this->flattenToBuffer(buffer, textBlobsOnly);
249 
250     // Pretend to serialize our sub-pictures for the side effect of filling typefaceSet
251     // with typefaces from sub-pictures.
252     struct DevNull: public SkWStream {
253         DevNull() : fBytesWritten(0) {}
254         size_t fBytesWritten;
255         bool write(const void*, size_t size) override { fBytesWritten += size; return true; }
256         size_t bytesWritten() const override { return fBytesWritten; }
257     } devnull;
258     for (const auto& pic : fPictures) {
259         pic->serialize(&devnull, nullptr, typefaceSet, /*textBlobsOnly=*/ true);
260     }
261     if (textBlobsOnly) { return; } // return early from fake serialize
262 
263     // We need to write factories before we write the buffer.
264     // We need to write typefaces before we write the buffer or any sub-picture.
265     WriteFactories(stream, factSet);
266     // Pass the original typefaceproc (if any) now that we're ready to actually serialize the
267     // typefaces. We skipped this proc before, when we were serializing paints, so that the
268     // paints would just write indices into our typeface set.
269     WriteTypefaces(stream, *typefaceSet, procs);
270 
271     // Write the buffer.
272     write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
273     buffer.writeToStream(stream);
274 
275     // Write sub-pictures by calling serialize again.
276     if (!fPictures.empty()) {
277         write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictures.size());
278         for (const auto& pic : fPictures) {
279             pic->serialize(stream, &procs, typefaceSet, /*textBlobsOnly=*/ false);
280         }
281     }
282 
283     stream->write32(SK_PICT_EOF_TAG);
284 }
285 
flatten(SkWriteBuffer & buffer) const286 void SkPictureData::flatten(SkWriteBuffer& buffer) const {
287     write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size());
288     buffer.writeByteArray(fOpData->bytes(), fOpData->size());
289 
290     if (!fPictures.empty()) {
291         write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictures.size());
292         for (const auto& pic : fPictures) {
293             SkPicturePriv::Flatten(pic, buffer);
294         }
295     }
296 
297     if (!fDrawables.empty()) {
298         write_tag_size(buffer, SK_PICT_DRAWABLE_TAG, fDrawables.size());
299         for (const auto& draw : fDrawables) {
300             buffer.writeFlattenable(draw.get());
301         }
302     }
303 
304     // Write this picture playback's data into a writebuffer
305     this->flattenToBuffer(buffer, false);
306     buffer.write32(SK_PICT_EOF_TAG);
307 }
308 
309 ///////////////////////////////////////////////////////////////////////////////
310 
parseStreamTag(SkStream * stream,uint32_t tag,uint32_t size,const SkDeserialProcs & procs,SkTypefacePlayback * topLevelTFPlayback,int recursionLimit)311 bool SkPictureData::parseStreamTag(SkStream* stream,
312                                    uint32_t tag,
313                                    uint32_t size,
314                                    const SkDeserialProcs& procs,
315                                    SkTypefacePlayback* topLevelTFPlayback,
316                                    int recursionLimit) {
317     switch (tag) {
318         case SK_PICT_READER_TAG:
319             SkASSERT(nullptr == fOpData);
320             fOpData = SkData::MakeFromStream(stream, size);
321             if (!fOpData) {
322                 return false;
323             }
324             break;
325         case SK_PICT_FACTORY_TAG: {
326             if (!stream->readU32(&size)) { return false; }
327             if (StreamRemainingLengthIsBelow(stream, size)) {
328                 return false;
329             }
330             fFactoryPlayback = std::make_unique<SkFactoryPlayback>(size);
331             for (size_t i = 0; i < size; i++) {
332                 SkString str;
333                 size_t len;
334                 if (!stream->readPackedUInt(&len)) { return false; }
335                 if (StreamRemainingLengthIsBelow(stream, len)) {
336                     return false;
337                 }
338                 str.resize(len);
339                 if (stream->read(str.data(), len) != len) {
340                     return false;
341                 }
342                 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
343             }
344         } break;
345         case SK_PICT_TYPEFACE_TAG: {
346             if (StreamRemainingLengthIsBelow(stream, size)) {
347                 return false;
348             }
349             fTFPlayback.setCount(size);
350             for (uint32_t i = 0; i < size; ++i) {
351                 if (stream->isAtEnd()) {
352                     return false;
353                 }
354                 sk_sp<SkTypeface> tf;
355                 if (procs.fTypefaceProc) {
356                     tf = procs.fTypefaceProc(&stream, sizeof(stream), procs.fTypefaceCtx);
357                 } else {
358                     tf = SkTypeface::MakeDeserialize(stream);
359                 }
360                 if (!tf) {    // failed to deserialize
361                     // fTFPlayback asserts it never has a null, so we plop in
362                     // the default here.
363                     tf = SkTypeface::MakeDefault();
364                 }
365                 fTFPlayback[i] = std::move(tf);
366             }
367         } break;
368         case SK_PICT_PICTURE_TAG: {
369             SkASSERT(fPictures.empty());
370             if (StreamRemainingLengthIsBelow(stream, size)) {
371                 return false;
372             }
373             fPictures.reserve_back(SkToInt(size));
374 
375             for (uint32_t i = 0; i < size; i++) {
376                 auto pic = SkPicture::MakeFromStreamPriv(stream, &procs,
377                                                          topLevelTFPlayback, recursionLimit - 1);
378                 if (!pic) {
379                     return false;
380                 }
381                 fPictures.push_back(std::move(pic));
382             }
383         } break;
384         case SK_PICT_BUFFER_SIZE_TAG: {
385             if (StreamRemainingLengthIsBelow(stream, size)) {
386                 return false;
387             }
388             SkAutoMalloc storage(size);
389             if (stream->read(storage.get(), size) != size) {
390                 return false;
391             }
392 
393             SkReadBuffer buffer(storage.get(), size);
394             buffer.setVersion(fInfo.getVersion());
395 
396             if (!fFactoryPlayback) {
397                 return false;
398             }
399             fFactoryPlayback->setupBuffer(buffer);
400             buffer.setDeserialProcs(procs);
401 
402             if (fTFPlayback.count() > 0) {
403                 // .skp files <= v43 have typefaces serialized with each sub picture.
404                 fTFPlayback.setupBuffer(buffer);
405             } else {
406                 // Newer .skp files serialize all typefaces with the top picture.
407                 topLevelTFPlayback->setupBuffer(buffer);
408             }
409 
410             while (!buffer.eof() && buffer.isValid()) {
411                 tag = buffer.readUInt();
412                 size = buffer.readUInt();
413                 this->parseBufferTag(buffer, tag, size);
414             }
415             if (!buffer.isValid()) {
416                 return false;
417             }
418         } break;
419     }
420     return true;    // success
421 }
422 
create_image_from_buffer(SkReadBuffer & buffer)423 static sk_sp<SkImage> create_image_from_buffer(SkReadBuffer& buffer) {
424     return buffer.readImage();
425 }
426 
create_drawable_from_buffer(SkReadBuffer & buffer)427 static sk_sp<SkDrawable> create_drawable_from_buffer(SkReadBuffer& buffer) {
428     return sk_sp<SkDrawable>((SkDrawable*)buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
429 }
430 
431 // We need two types 'cause SkDrawable is const-variant.
432 template <typename T, typename U>
new_array_from_buffer(SkReadBuffer & buffer,uint32_t inCount,SkTArray<sk_sp<T>> & array,sk_sp<U> (* factory)(SkReadBuffer &))433 bool new_array_from_buffer(SkReadBuffer& buffer, uint32_t inCount,
434                            SkTArray<sk_sp<T>>& array, sk_sp<U> (*factory)(SkReadBuffer&)) {
435     if (!buffer.validate(array.empty() && SkTFitsIn<int>(inCount))) {
436         return false;
437     }
438     if (0 == inCount) {
439         return true;
440     }
441 
442     for (uint32_t i = 0; i < inCount; ++i) {
443         auto obj = factory(buffer);
444 
445         if (!buffer.validate(obj != nullptr)) {
446             array.clear();
447             return false;
448         }
449 
450         array.push_back(std::move(obj));
451     }
452 
453     return true;
454 }
455 
parseBufferTag(SkReadBuffer & buffer,uint32_t tag,uint32_t size)456 void SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t size) {
457     switch (tag) {
458         case SK_PICT_PAINT_BUFFER_TAG: {
459             if (!buffer.validate(SkTFitsIn<int>(size))) {
460                 return;
461             }
462             const int count = SkToInt(size);
463 
464             for (int i = 0; i < count; ++i) {
465                 fPaints.push_back(buffer.readPaint());
466                 if (!buffer.isValid()) {
467                     return;
468                 }
469             }
470         } break;
471         case SK_PICT_PATH_BUFFER_TAG:
472             if (size > 0) {
473                 const int count = buffer.readInt();
474                 if (!buffer.validate(count >= 0)) {
475                     return;
476                 }
477                 for (int i = 0; i < count; i++) {
478                     buffer.readPath(&fPaths.push_back());
479                     if (!buffer.isValid()) {
480                         return;
481                     }
482                 }
483             } break;
484         case SK_PICT_TEXTBLOB_BUFFER_TAG:
485             new_array_from_buffer(buffer, size, fTextBlobs, SkTextBlobPriv::MakeFromBuffer);
486             break;
487         case SK_PICT_SLUG_BUFFER_TAG:
488 #if defined(SK_GANESH)
489             new_array_from_buffer(buffer, size, fSlugs, sktext::gpu::Slug::MakeFromBuffer);
490 #endif
491             break;
492         case SK_PICT_VERTICES_BUFFER_TAG:
493             new_array_from_buffer(buffer, size, fVertices, SkVerticesPriv::Decode);
494             break;
495         case SK_PICT_IMAGE_BUFFER_TAG:
496             new_array_from_buffer(buffer, size, fImages, create_image_from_buffer);
497             break;
498         case SK_PICT_READER_TAG: {
499             // Preflight check that we can initialize all data from the buffer
500             // before allocating it.
501             if (!buffer.validateCanReadN<uint8_t>(size)) {
502                 return;
503             }
504             auto data(SkData::MakeUninitialized(size));
505             if (!buffer.readByteArray(data->writable_data(), size) ||
506                 !buffer.validate(nullptr == fOpData)) {
507                 return;
508             }
509             SkASSERT(nullptr == fOpData);
510             fOpData = std::move(data);
511         } break;
512         case SK_PICT_PICTURE_TAG:
513             new_array_from_buffer(buffer, size, fPictures, SkPicturePriv::MakeFromBuffer);
514             break;
515         case SK_PICT_DRAWABLE_TAG:
516             new_array_from_buffer(buffer, size, fDrawables, create_drawable_from_buffer);
517             break;
518         default:
519             buffer.validate(false); // The tag was invalid.
520             break;
521     }
522 }
523 
CreateFromStream(SkStream * stream,const SkPictInfo & info,const SkDeserialProcs & procs,SkTypefacePlayback * topLevelTFPlayback,int recursionLimit)524 SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
525                                                const SkPictInfo& info,
526                                                const SkDeserialProcs& procs,
527                                                SkTypefacePlayback* topLevelTFPlayback,
528                                                int recursionLimit) {
529     std::unique_ptr<SkPictureData> data(new SkPictureData(info));
530     if (!topLevelTFPlayback) {
531         topLevelTFPlayback = &data->fTFPlayback;
532     }
533 
534     if (!data->parseStream(stream, procs, topLevelTFPlayback, recursionLimit)) {
535         return nullptr;
536     }
537     return data.release();
538 }
539 
CreateFromBuffer(SkReadBuffer & buffer,const SkPictInfo & info)540 SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer,
541                                                const SkPictInfo& info) {
542     std::unique_ptr<SkPictureData> data(new SkPictureData(info));
543     buffer.setVersion(info.getVersion());
544 
545     if (!data->parseBuffer(buffer)) {
546         return nullptr;
547     }
548     return data.release();
549 }
550 
parseStream(SkStream * stream,const SkDeserialProcs & procs,SkTypefacePlayback * topLevelTFPlayback,int recursionLimit)551 bool SkPictureData::parseStream(SkStream* stream,
552                                 const SkDeserialProcs& procs,
553                                 SkTypefacePlayback* topLevelTFPlayback,
554                                 int recursionLimit) {
555     for (;;) {
556         uint32_t tag;
557         if (!stream->readU32(&tag)) { return false; }
558         if (SK_PICT_EOF_TAG == tag) {
559             break;
560         }
561 
562         uint32_t size;
563         if (!stream->readU32(&size)) { return false; }
564         if (!this->parseStreamTag(stream, tag, size, procs, topLevelTFPlayback, recursionLimit)) {
565             return false; // we're invalid
566         }
567     }
568     return true;
569 }
570 
parseBuffer(SkReadBuffer & buffer)571 bool SkPictureData::parseBuffer(SkReadBuffer& buffer) {
572     while (buffer.isValid()) {
573         uint32_t tag = buffer.readUInt();
574         if (SK_PICT_EOF_TAG == tag) {
575             break;
576         }
577         this->parseBufferTag(buffer, tag, buffer.readUInt());
578     }
579 
580     // Check that we encountered required tags
581     if (!buffer.validate(this->opData() != nullptr)) {
582         // If we didn't build any opData, we are invalid. Even an EmptyPicture allocates the
583         // SkData for the ops (though its length may be zero).
584         return false;
585     }
586     return true;
587 }
588 
optionalPaint(SkReadBuffer * reader) const589 const SkPaint* SkPictureData::optionalPaint(SkReadBuffer* reader) const {
590     int index = reader->readInt();
591     if (index == 0) {
592         return nullptr; // recorder wrote a zero for no paint (likely drawimage)
593     }
594     return reader->validate(index > 0 && index <= fPaints.size()) ?
595         &fPaints[index - 1] : nullptr;
596 }
597 
requiredPaint(SkReadBuffer * reader) const598 const SkPaint& SkPictureData::requiredPaint(SkReadBuffer* reader) const {
599     const SkPaint* paint = this->optionalPaint(reader);
600     if (reader->validate(paint != nullptr)) {
601         return *paint;
602     }
603     static const SkPaint& stub = *(new SkPaint);
604     return stub;
605 }
606