1 /*
2  * Copyright 2007 The Android Open Source Project
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 "SkPicture.h"
9 
10 #include "SkImageGenerator.h"
11 #include "SkMathPriv.h"
12 #include "SkPictureCommon.h"
13 #include "SkPictureData.h"
14 #include "SkPicturePlayback.h"
15 #include "SkPicturePriv.h"
16 #include "SkPictureRecord.h"
17 #include "SkPictureRecorder.h"
18 #include "SkSerialProcs.h"
19 #include "SkTo.h"
20 #include <atomic>
21 
22 // When we read/write the SkPictInfo via a stream, we have a sentinel byte right after the info.
23 // Note: in the read/write buffer versions, we have a slightly different convention:
24 //      We have a sentinel int32_t:
25 //          0 : failure
26 //          1 : PictureData
27 //         <0 : -size of the custom data
28 enum {
29     kFailure_TrailingStreamByteAfterPictInfo     = 0,   // nothing follows
30     kPictureData_TrailingStreamByteAfterPictInfo = 1,   // SkPictureData follows
31     kCustom_TrailingStreamByteAfterPictInfo      = 2,   // -size32 follows
32 };
33 
34 /* SkPicture impl.  This handles generic responsibilities like unique IDs and serialization. */
35 
SkPicture()36 SkPicture::SkPicture() {
37     static std::atomic<uint32_t> nextID{1};
38     do {
39         fUniqueID = nextID.fetch_add(+1, std::memory_order_relaxed);
40     } while (fUniqueID == 0);
41 }
42 
43 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
44 
createHeader() const45 SkPictInfo SkPicture::createHeader() const {
46     SkPictInfo info;
47     // Copy magic bytes at the beginning of the header
48     static_assert(sizeof(kMagic) == 8, "");
49     static_assert(sizeof(kMagic) == sizeof(info.fMagic), "");
50     memcpy(info.fMagic, kMagic, sizeof(kMagic));
51 
52     // Set picture info after magic bytes in the header
53     info.setVersion(CURRENT_PICTURE_VERSION);
54     info.fCullRect = this->cullRect();
55     return info;
56 }
57 
IsValidPictInfo(const SkPictInfo & info)58 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) {
59     if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) {
60         return false;
61     }
62     if (info.getVersion() < MIN_PICTURE_VERSION || info.getVersion() > CURRENT_PICTURE_VERSION) {
63         return false;
64     }
65     return true;
66 }
67 
StreamIsSKP(SkStream * stream,SkPictInfo * pInfo)68 bool SkPicture::StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
69     if (!stream) {
70         return false;
71     }
72 
73     SkPictInfo info;
74     SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
75     if (stream->read(&info.fMagic, sizeof(kMagic)) != sizeof(kMagic)) {
76         return false;
77     }
78 
79     uint32_t version;
80     if (!stream->readU32(&version)) { return false; }
81     info.setVersion(version);
82     if (!stream->readScalar(&info.fCullRect.fLeft  )) { return false; }
83     if (!stream->readScalar(&info.fCullRect.fTop   )) { return false; }
84     if (!stream->readScalar(&info.fCullRect.fRight )) { return false; }
85     if (!stream->readScalar(&info.fCullRect.fBottom)) { return false; }
86     if (info.getVersion() < SkReadBuffer::kRemoveHeaderFlags_Version) {
87         if (!stream->readU32(nullptr)) { return false; }
88     }
89 
90     if (!IsValidPictInfo(info)) { return false; }
91 
92     if (pInfo) { *pInfo = info; }
93     return true;
94 }
SkPicture_StreamIsSKP(SkStream * stream,SkPictInfo * pInfo)95 bool SkPicture_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
96     return SkPicture::StreamIsSKP(stream, pInfo);
97 }
98 
BufferIsSKP(SkReadBuffer * buffer,SkPictInfo * pInfo)99 bool SkPicture::BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo) {
100     SkPictInfo info;
101     SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
102     if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) {
103         return false;
104     }
105 
106     info.setVersion(buffer->readUInt());
107     buffer->readRect(&info.fCullRect);
108     if (info.getVersion() < SkReadBuffer::kRemoveHeaderFlags_Version) {
109         (void)buffer->readUInt();   // used to be flags
110     }
111 
112     if (IsValidPictInfo(info)) {
113         if (pInfo) { *pInfo = info; }
114         return true;
115     }
116     return false;
117 }
118 
Forwardport(const SkPictInfo & info,const SkPictureData * data,SkReadBuffer * buffer)119 sk_sp<SkPicture> SkPicture::Forwardport(const SkPictInfo& info,
120                                         const SkPictureData* data,
121                                         SkReadBuffer* buffer) {
122     if (!data) {
123         return nullptr;
124     }
125     if (!data->opData()) {
126         return nullptr;
127     }
128     SkPicturePlayback playback(data);
129     SkPictureRecorder r;
130     playback.draw(r.beginRecording(info.fCullRect), nullptr/*no callback*/, buffer);
131     return r.finishRecordingAsPicture();
132 }
133 
MakeFromStream(SkStream * stream,const SkDeserialProcs * procs)134 sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, const SkDeserialProcs* procs) {
135     return MakeFromStream(stream, procs, nullptr);
136 }
137 
MakeFromData(const void * data,size_t size,const SkDeserialProcs * procs)138 sk_sp<SkPicture> SkPicture::MakeFromData(const void* data, size_t size,
139                                          const SkDeserialProcs* procs) {
140     if (!data) {
141         return nullptr;
142     }
143     SkMemoryStream stream(data, size);
144     return MakeFromStream(&stream, procs, nullptr);
145 }
146 
MakeFromData(const SkData * data,const SkDeserialProcs * procs)147 sk_sp<SkPicture> SkPicture::MakeFromData(const SkData* data, const SkDeserialProcs* procs) {
148     if (!data) {
149         return nullptr;
150     }
151     SkMemoryStream stream(data->data(), data->size());
152     return MakeFromStream(&stream, procs, nullptr);
153 }
154 
MakeFromStream(SkStream * stream,const SkDeserialProcs * procsPtr,SkTypefacePlayback * typefaces)155 sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, const SkDeserialProcs* procsPtr,
156                                            SkTypefacePlayback* typefaces) {
157     SkPictInfo info;
158     if (!StreamIsSKP(stream, &info)) {
159         return nullptr;
160     }
161 
162     SkDeserialProcs procs;
163     if (procsPtr) {
164         procs = *procsPtr;
165     }
166 
167     uint8_t trailingStreamByteAfterPictInfo;
168     if (!stream->readU8(&trailingStreamByteAfterPictInfo)) { return nullptr; }
169     switch (trailingStreamByteAfterPictInfo) {
170         case kPictureData_TrailingStreamByteAfterPictInfo: {
171             std::unique_ptr<SkPictureData> data(
172                     SkPictureData::CreateFromStream(stream, info, procs, typefaces));
173             return Forwardport(info, data.get(), nullptr);
174         }
175         case kCustom_TrailingStreamByteAfterPictInfo: {
176             int32_t ssize;
177             if (!stream->readS32(&ssize) || ssize >= 0 || !procs.fPictureProc) {
178                 return nullptr;
179             }
180             size_t size = sk_negate_to_size_t(ssize);
181             auto data = SkData::MakeUninitialized(size);
182             if (stream->read(data->writable_data(), size) != size) {
183                 return nullptr;
184             }
185             return procs.fPictureProc(data->data(), size, procs.fPictureCtx);
186         }
187         default:    // fall through to error return
188             break;
189     }
190     return nullptr;
191 }
192 
MakeFromBuffer(SkReadBuffer & buffer)193 sk_sp<SkPicture> SkPicturePriv::MakeFromBuffer(SkReadBuffer& buffer) {
194     SkPictInfo info;
195     if (!SkPicture::BufferIsSKP(&buffer, &info)) {
196         return nullptr;
197     }
198     // size should be 0, 1, or negative
199     int32_t ssize = buffer.read32();
200     if (ssize < 0) {
201         const SkDeserialProcs& procs = buffer.getDeserialProcs();
202         if (!procs.fPictureProc) {
203             return nullptr;
204         }
205         size_t size = sk_negate_to_size_t(ssize);
206         return procs.fPictureProc(buffer.skip(size), size, procs.fPictureCtx);
207     }
208     if (ssize != 1) {
209         // 1 is the magic 'size' that means SkPictureData follows
210         return nullptr;
211     }
212    std::unique_ptr<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, info));
213     return SkPicture::Forwardport(info, data.get(), &buffer);
214 }
215 
backport() const216 SkPictureData* SkPicture::backport() const {
217     SkPictInfo info = this->createHeader();
218     SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.height()), 0/*flags*/);
219     rec.beginRecording();
220         this->playback(&rec);
221     rec.endRecording();
222     return new SkPictureData(rec, info);
223 }
224 
serialize(SkWStream * stream,const SkSerialProcs * procs) const225 void SkPicture::serialize(SkWStream* stream, const SkSerialProcs* procs) const {
226     this->serialize(stream, procs, nullptr);
227 }
228 
serialize(const SkSerialProcs * procs) const229 sk_sp<SkData> SkPicture::serialize(const SkSerialProcs* procs) const {
230     SkDynamicMemoryWStream stream;
231     this->serialize(&stream, procs, nullptr);
232     return stream.detachAsData();
233 }
234 
custom_serialize(const SkPicture * picture,const SkSerialProcs & procs)235 static sk_sp<SkData> custom_serialize(const SkPicture* picture, const SkSerialProcs& procs) {
236     if (procs.fPictureProc) {
237         auto data = procs.fPictureProc(const_cast<SkPicture*>(picture), procs.fPictureCtx);
238         if (data) {
239             size_t size = data->size();
240             if (!SkTFitsIn<int32_t>(size) || size <= 1) {
241                 return SkData::MakeEmpty();
242             }
243             return data;
244         }
245     }
246     return nullptr;
247 }
248 
write_pad32(SkWStream * stream,const void * data,size_t size)249 static bool write_pad32(SkWStream* stream, const void* data, size_t size) {
250     if (!stream->write(data, size)) {
251         return false;
252     }
253     if (size & 3) {
254         uint32_t zero = 0;
255         return stream->write(&zero, 4 - (size & 3));
256     }
257     return true;
258 }
259 
serialize(SkWStream * stream,const SkSerialProcs * procsPtr,SkRefCntSet * typefaceSet) const260 void SkPicture::serialize(SkWStream* stream, const SkSerialProcs* procsPtr,
261                           SkRefCntSet* typefaceSet) const {
262     SkSerialProcs procs;
263     if (procsPtr) {
264         procs = *procsPtr;
265     }
266 
267     SkPictInfo info = this->createHeader();
268     stream->write(&info, sizeof(info));
269 
270     if (auto custom = custom_serialize(this, procs)) {
271         int32_t size = SkToS32(custom->size());
272         if (size == 0) {
273             stream->write8(kFailure_TrailingStreamByteAfterPictInfo);
274             return;
275         }
276         stream->write8(kCustom_TrailingStreamByteAfterPictInfo);
277         stream->write32(-size);    // negative for custom format
278         write_pad32(stream, custom->data(), size);
279         return;
280     }
281 
282     std::unique_ptr<SkPictureData> data(this->backport());
283     if (data) {
284         stream->write8(kPictureData_TrailingStreamByteAfterPictInfo);
285         data->serialize(stream, procs, typefaceSet);
286     } else {
287         stream->write8(kFailure_TrailingStreamByteAfterPictInfo);
288     }
289 }
290 
Flatten(const sk_sp<const SkPicture> picture,SkWriteBuffer & buffer)291 void SkPicturePriv::Flatten(const sk_sp<const SkPicture> picture, SkWriteBuffer& buffer) {
292     SkPictInfo info = picture->createHeader();
293     std::unique_ptr<SkPictureData> data(picture->backport());
294 
295     buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic));
296     buffer.writeUInt(info.getVersion());
297     buffer.writeRect(info.fCullRect);
298 
299     if (auto custom = custom_serialize(picture.get(), buffer.fProcs)) {
300         int32_t size = SkToS32(custom->size());
301         buffer.write32(-size);    // negative for custom format
302         buffer.writePad32(custom->data(), size);
303         return;
304     }
305 
306     if (data) {
307         buffer.write32(1); // special size meaning SkPictureData
308         data->flatten(buffer);
309     } else {
310         buffer.write32(0); // signal no content
311     }
312 }
313 
MakePlaceholder(SkRect cull)314 sk_sp<SkPicture> SkPicture::MakePlaceholder(SkRect cull) {
315     struct Placeholder : public SkPicture {
316           explicit Placeholder(SkRect cull) : fCull(cull) {}
317 
318           void playback(SkCanvas*, AbortCallback*) const override { }
319 
320           // approximateOpCount() needs to be greater than kMaxPictureOpsToUnrollInsteadOfRef
321           // in SkCanvas.cpp to avoid that unrolling.  SK_MaxS32 can't not be big enough!
322           int    approximateOpCount()   const override { return SK_MaxS32; }
323           size_t approximateBytesUsed() const override { return sizeof(*this); }
324           SkRect cullRect()             const override { return fCull; }
325 
326           SkRect fCull;
327     };
328     return sk_make_sp<Placeholder>(cull);
329 }
330