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