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