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 "SkAtomics.h"
9 #include "SkImageDeserializer.h"
10 #include "SkImageGenerator.h"
11 #include "SkMessageBus.h"
12 #include "SkPicture.h"
13 #include "SkPictureData.h"
14 #include "SkPicturePlayback.h"
15 #include "SkPictureRecord.h"
16 #include "SkPictureRecorder.h"
17 
18 #if defined(SK_DISALLOW_CROSSPROCESS_PICTUREIMAGEFILTERS) || \
19     defined(SK_ENABLE_PICTURE_IO_SECURITY_PRECAUTIONS)
20 static bool g_AllPictureIOSecurityPrecautionsEnabled = true;
21 #else
22 static bool g_AllPictureIOSecurityPrecautionsEnabled = false;
23 #endif
24 
25 DECLARE_SKMESSAGEBUS_MESSAGE(SkPicture::DeletionMessage);
26 
27 /* SkPicture impl.  This handles generic responsibilities like unique IDs and serialization. */
28 
SkPicture()29 SkPicture::SkPicture() : fUniqueID(0) {}
30 
~SkPicture()31 SkPicture::~SkPicture() {
32     // TODO: move this to ~SkBigPicture() only?
33 
34     // If the ID is still zero, no one has read it, so no need to send this message.
35     uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed);
36     if (id != 0) {
37         SkPicture::DeletionMessage msg = { (int32_t)id };
38         SkMessageBus<SkPicture::DeletionMessage>::Post(msg);
39     }
40 }
41 
uniqueID() const42 uint32_t SkPicture::uniqueID() const {
43     static uint32_t gNextID = 1;
44     uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed);
45     while (id == 0) {
46         uint32_t next = sk_atomic_fetch_add(&gNextID, 1u);
47         if (sk_atomic_compare_exchange(&fUniqueID, &id, next,
48                                        sk_memory_order_relaxed,
49                                        sk_memory_order_relaxed)) {
50             id = next;
51         } else {
52             // sk_atomic_compare_exchange replaced id with the current value of fUniqueID.
53         }
54     }
55     return id;
56 }
57 
58 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
59 
createHeader() const60 SkPictInfo SkPicture::createHeader() const {
61     SkPictInfo info;
62     // Copy magic bytes at the beginning of the header
63     static_assert(sizeof(kMagic) == 8, "");
64     static_assert(sizeof(kMagic) == sizeof(info.fMagic), "");
65     memcpy(info.fMagic, kMagic, sizeof(kMagic));
66 
67     // Set picture info after magic bytes in the header
68     info.setVersion(CURRENT_PICTURE_VERSION);
69     info.fCullRect = this->cullRect();
70     info.fFlags = SkPictInfo::kCrossProcess_Flag;
71     // TODO: remove this flag, since we're always float (now)
72     info.fFlags |= SkPictInfo::kScalarIsFloat_Flag;
73 
74     if (8 == sizeof(void*)) {
75         info.fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
76     }
77     return info;
78 }
79 
IsValidPictInfo(const SkPictInfo & info)80 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) {
81     if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) {
82         return false;
83     }
84     if (info.getVersion() < MIN_PICTURE_VERSION || info.getVersion() > CURRENT_PICTURE_VERSION) {
85         return false;
86     }
87     return true;
88 }
89 
InternalOnly_StreamIsSKP(SkStream * stream,SkPictInfo * pInfo)90 bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
91     if (!stream) {
92         return false;
93     }
94 
95     SkPictInfo info;
96     SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
97     if (!stream->read(&info.fMagic, sizeof(kMagic))) {
98         return false;
99     }
100 
101     info.setVersion(         stream->readU32());
102     info.fCullRect.fLeft   = stream->readScalar();
103     info.fCullRect.fTop    = stream->readScalar();
104     info.fCullRect.fRight  = stream->readScalar();
105     info.fCullRect.fBottom = stream->readScalar();
106     info.fFlags            = stream->readU32();
107 
108     if (IsValidPictInfo(info)) {
109         if (pInfo) { *pInfo = info; }
110         return true;
111     }
112     return false;
113 }
114 
InternalOnly_BufferIsSKP(SkReadBuffer * buffer,SkPictInfo * pInfo)115 bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo) {
116     SkPictInfo info;
117     SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
118     if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) {
119         return false;
120     }
121 
122     info.setVersion(buffer->readUInt());
123     buffer->readRect(&info.fCullRect);
124     info.fFlags = buffer->readUInt();
125 
126     if (IsValidPictInfo(info)) {
127         if (pInfo) { *pInfo = info; }
128         return true;
129     }
130     return false;
131 }
132 
Forwardport(const SkPictInfo & info,const SkPictureData * data,SkReadBuffer * buffer)133 sk_sp<SkPicture> SkPicture::Forwardport(const SkPictInfo& info,
134                                         const SkPictureData* data,
135                                         SkReadBuffer* buffer) {
136     if (!data) {
137         return nullptr;
138     }
139     SkPicturePlayback playback(data);
140     SkPictureRecorder r;
141     playback.draw(r.beginRecording(info.fCullRect), nullptr/*no callback*/, buffer);
142     return r.finishRecordingAsPicture();
143 }
144 
MakeFromStream(SkStream * stream,SkImageDeserializer * factory)145 sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, SkImageDeserializer* factory) {
146     return MakeFromStream(stream, factory, nullptr);
147 }
148 
MakeFromStream(SkStream * stream)149 sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream) {
150     SkImageDeserializer factory;
151     return MakeFromStream(stream, &factory);
152 }
153 
MakeFromData(const void * data,size_t size,SkImageDeserializer * factory)154 sk_sp<SkPicture> SkPicture::MakeFromData(const void* data, size_t size,
155                                          SkImageDeserializer* factory) {
156     SkMemoryStream stream(data, size);
157     return MakeFromStream(&stream, factory, nullptr);
158 }
159 
MakeFromData(const SkData * data,SkImageDeserializer * factory)160 sk_sp<SkPicture> SkPicture::MakeFromData(const SkData* data, SkImageDeserializer* factory) {
161     if (!data) {
162         return nullptr;
163     }
164     SkMemoryStream stream(data->data(), data->size());
165     return MakeFromStream(&stream, factory, nullptr);
166 }
167 
MakeFromStream(SkStream * stream,SkImageDeserializer * factory,SkTypefacePlayback * typefaces)168 sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, SkImageDeserializer* factory,
169                                            SkTypefacePlayback* typefaces) {
170     SkPictInfo info;
171     if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) {
172         return nullptr;
173     }
174     std::unique_ptr<SkPictureData> data(
175             SkPictureData::CreateFromStream(stream, info, factory, typefaces));
176     return Forwardport(info, data.get(), nullptr);
177 }
178 
MakeFromBuffer(SkReadBuffer & buffer)179 sk_sp<SkPicture> SkPicture::MakeFromBuffer(SkReadBuffer& buffer) {
180     SkPictInfo info;
181     if (!InternalOnly_BufferIsSKP(&buffer, &info) || !buffer.readBool()) {
182         return nullptr;
183     }
184     std::unique_ptr<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, info));
185     return Forwardport(info, data.get(), &buffer);
186 }
187 
backport() const188 SkPictureData* SkPicture::backport() const {
189     SkPictInfo info = this->createHeader();
190     SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.height()), 0/*flags*/);
191     rec.beginRecording();
192         this->playback(&rec);
193     rec.endRecording();
194     return new SkPictureData(rec, info);
195 }
196 
serialize(SkWStream * stream,SkPixelSerializer * pixelSerializer) const197 void SkPicture::serialize(SkWStream* stream, SkPixelSerializer* pixelSerializer) const {
198     this->serialize(stream, pixelSerializer, nullptr);
199 }
200 
serialize(SkPixelSerializer * pixelSerializer) const201 sk_sp<SkData> SkPicture::serialize(SkPixelSerializer* pixelSerializer) const {
202     SkDynamicMemoryWStream stream;
203     this->serialize(&stream, pixelSerializer, nullptr);
204     return stream.detachAsData();
205 }
206 
serialize(SkWStream * stream,SkPixelSerializer * pixelSerializer,SkRefCntSet * typefaceSet) const207 void SkPicture::serialize(SkWStream* stream,
208                           SkPixelSerializer* pixelSerializer,
209                           SkRefCntSet* typefaceSet) const {
210     SkPictInfo info = this->createHeader();
211     std::unique_ptr<SkPictureData> data(this->backport());
212 
213     stream->write(&info, sizeof(info));
214     if (data) {
215         stream->writeBool(true);
216         data->serialize(stream, pixelSerializer, typefaceSet);
217     } else {
218         stream->writeBool(false);
219     }
220 }
221 
flatten(SkWriteBuffer & buffer) const222 void SkPicture::flatten(SkWriteBuffer& buffer) const {
223     SkPictInfo info = this->createHeader();
224     std::unique_ptr<SkPictureData> data(this->backport());
225 
226     buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic));
227     buffer.writeUInt(info.getVersion());
228     buffer.writeRect(info.fCullRect);
229     buffer.writeUInt(info.fFlags);
230     if (data) {
231         buffer.writeBool(true);
232         data->flatten(buffer);
233     } else {
234         buffer.writeBool(false);
235     }
236 }
237 
238 #ifdef SK_SUPPORT_LEGACY_PICTURE_GPUVETO
suitableForGpuRasterization(GrContext *,const char ** whyNot) const239 bool SkPicture::suitableForGpuRasterization(GrContext*, const char** whyNot) const {
240     if (this->numSlowPaths() > 5) {
241         if (whyNot) { *whyNot = "Too many slow paths (either concave or dashed)."; }
242         return false;
243     }
244     return true;
245 }
246 #endif
247 
248 // Global setting to disable security precautions for serialization.
SetPictureIOSecurityPrecautionsEnabled_Dangerous(bool set)249 void SkPicture::SetPictureIOSecurityPrecautionsEnabled_Dangerous(bool set) {
250     g_AllPictureIOSecurityPrecautionsEnabled = set;
251 }
252 
PictureIOSecurityPrecautionsEnabled()253 bool SkPicture::PictureIOSecurityPrecautionsEnabled() {
254     return g_AllPictureIOSecurityPrecautionsEnabled;
255 }
256