Line data Source code
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 0 : DECLARE_SKMESSAGEBUS_MESSAGE(SkPicture::DeletionMessage);
26 :
27 : /* SkPicture impl. This handles generic responsibilities like unique IDs and serialization. */
28 :
29 0 : SkPicture::SkPicture() : fUniqueID(0) {}
30 :
31 0 : 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 0 : uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed);
36 0 : if (id != 0) {
37 0 : SkPicture::DeletionMessage msg = { (int32_t)id };
38 0 : SkMessageBus<SkPicture::DeletionMessage>::Post(msg);
39 : }
40 0 : }
41 :
42 0 : uint32_t SkPicture::uniqueID() const {
43 : static uint32_t gNextID = 1;
44 0 : uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed);
45 0 : while (id == 0) {
46 0 : uint32_t next = sk_atomic_fetch_add(&gNextID, 1u);
47 0 : if (sk_atomic_compare_exchange(&fUniqueID, &id, next,
48 : sk_memory_order_relaxed,
49 : sk_memory_order_relaxed)) {
50 0 : id = next;
51 : } else {
52 : // sk_atomic_compare_exchange replaced id with the current value of fUniqueID.
53 : }
54 : }
55 0 : return id;
56 : }
57 :
58 : static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
59 :
60 0 : SkPictInfo SkPicture::createHeader() const {
61 0 : 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 0 : memcpy(info.fMagic, kMagic, sizeof(kMagic));
66 :
67 : // Set picture info after magic bytes in the header
68 0 : info.setVersion(CURRENT_PICTURE_VERSION);
69 0 : info.fCullRect = this->cullRect();
70 0 : info.fFlags = SkPictInfo::kCrossProcess_Flag;
71 : // TODO: remove this flag, since we're always float (now)
72 0 : info.fFlags |= SkPictInfo::kScalarIsFloat_Flag;
73 :
74 : if (8 == sizeof(void*)) {
75 0 : info.fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
76 : }
77 0 : return info;
78 : }
79 :
80 0 : bool SkPicture::IsValidPictInfo(const SkPictInfo& info) {
81 0 : if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) {
82 0 : return false;
83 : }
84 0 : if (info.getVersion() < MIN_PICTURE_VERSION || info.getVersion() > CURRENT_PICTURE_VERSION) {
85 0 : return false;
86 : }
87 0 : return true;
88 : }
89 :
90 0 : bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
91 0 : if (!stream) {
92 0 : return false;
93 : }
94 :
95 0 : SkPictInfo info;
96 : SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
97 0 : if (!stream->read(&info.fMagic, sizeof(kMagic))) {
98 0 : return false;
99 : }
100 :
101 0 : info.setVersion( stream->readU32());
102 0 : info.fCullRect.fLeft = stream->readScalar();
103 0 : info.fCullRect.fTop = stream->readScalar();
104 0 : info.fCullRect.fRight = stream->readScalar();
105 0 : info.fCullRect.fBottom = stream->readScalar();
106 0 : info.fFlags = stream->readU32();
107 :
108 0 : if (IsValidPictInfo(info)) {
109 0 : if (pInfo) { *pInfo = info; }
110 0 : return true;
111 : }
112 0 : return false;
113 : }
114 :
115 0 : bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo) {
116 0 : SkPictInfo info;
117 : SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
118 0 : if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) {
119 0 : return false;
120 : }
121 :
122 0 : info.setVersion(buffer->readUInt());
123 0 : buffer->readRect(&info.fCullRect);
124 0 : info.fFlags = buffer->readUInt();
125 :
126 0 : if (IsValidPictInfo(info)) {
127 0 : if (pInfo) { *pInfo = info; }
128 0 : return true;
129 : }
130 0 : return false;
131 : }
132 :
133 0 : sk_sp<SkPicture> SkPicture::Forwardport(const SkPictInfo& info,
134 : const SkPictureData* data,
135 : SkReadBuffer* buffer) {
136 0 : if (!data) {
137 0 : return nullptr;
138 : }
139 0 : SkPicturePlayback playback(data);
140 0 : SkPictureRecorder r;
141 0 : playback.draw(r.beginRecording(info.fCullRect), nullptr/*no callback*/, buffer);
142 0 : return r.finishRecordingAsPicture();
143 : }
144 :
145 0 : sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, SkImageDeserializer* factory) {
146 0 : return MakeFromStream(stream, factory, nullptr);
147 : }
148 :
149 0 : sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream) {
150 0 : SkImageDeserializer factory;
151 0 : return MakeFromStream(stream, &factory);
152 : }
153 :
154 0 : sk_sp<SkPicture> SkPicture::MakeFromData(const void* data, size_t size,
155 : SkImageDeserializer* factory) {
156 0 : SkMemoryStream stream(data, size);
157 0 : return MakeFromStream(&stream, factory, nullptr);
158 : }
159 :
160 0 : sk_sp<SkPicture> SkPicture::MakeFromData(const SkData* data, SkImageDeserializer* factory) {
161 0 : if (!data) {
162 0 : return nullptr;
163 : }
164 0 : SkMemoryStream stream(data->data(), data->size());
165 0 : return MakeFromStream(&stream, factory, nullptr);
166 : }
167 :
168 0 : sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, SkImageDeserializer* factory,
169 : SkTypefacePlayback* typefaces) {
170 0 : SkPictInfo info;
171 0 : if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) {
172 0 : return nullptr;
173 : }
174 : std::unique_ptr<SkPictureData> data(
175 0 : SkPictureData::CreateFromStream(stream, info, factory, typefaces));
176 0 : return Forwardport(info, data.get(), nullptr);
177 : }
178 :
179 0 : sk_sp<SkPicture> SkPicture::MakeFromBuffer(SkReadBuffer& buffer) {
180 0 : SkPictInfo info;
181 0 : if (!InternalOnly_BufferIsSKP(&buffer, &info) || !buffer.readBool()) {
182 0 : return nullptr;
183 : }
184 0 : std::unique_ptr<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, info));
185 0 : return Forwardport(info, data.get(), &buffer);
186 : }
187 :
188 0 : SkPictureData* SkPicture::backport() const {
189 0 : SkPictInfo info = this->createHeader();
190 0 : SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.height()), 0/*flags*/);
191 0 : rec.beginRecording();
192 0 : this->playback(&rec);
193 0 : rec.endRecording();
194 0 : return new SkPictureData(rec, info);
195 : }
196 :
197 0 : void SkPicture::serialize(SkWStream* stream, SkPixelSerializer* pixelSerializer) const {
198 0 : this->serialize(stream, pixelSerializer, nullptr);
199 0 : }
200 :
201 0 : sk_sp<SkData> SkPicture::serialize(SkPixelSerializer* pixelSerializer) const {
202 0 : SkDynamicMemoryWStream stream;
203 0 : this->serialize(&stream, pixelSerializer, nullptr);
204 0 : return stream.detachAsData();
205 : }
206 :
207 0 : void SkPicture::serialize(SkWStream* stream,
208 : SkPixelSerializer* pixelSerializer,
209 : SkRefCntSet* typefaceSet) const {
210 0 : SkPictInfo info = this->createHeader();
211 0 : std::unique_ptr<SkPictureData> data(this->backport());
212 :
213 0 : stream->write(&info, sizeof(info));
214 0 : if (data) {
215 0 : stream->writeBool(true);
216 0 : data->serialize(stream, pixelSerializer, typefaceSet);
217 : } else {
218 0 : stream->writeBool(false);
219 : }
220 0 : }
221 :
222 0 : void SkPicture::flatten(SkWriteBuffer& buffer) const {
223 0 : SkPictInfo info = this->createHeader();
224 0 : std::unique_ptr<SkPictureData> data(this->backport());
225 :
226 0 : buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic));
227 0 : buffer.writeUInt(info.getVersion());
228 0 : buffer.writeRect(info.fCullRect);
229 0 : buffer.writeUInt(info.fFlags);
230 0 : if (data) {
231 0 : buffer.writeBool(true);
232 0 : data->flatten(buffer);
233 : } else {
234 0 : buffer.writeBool(false);
235 : }
236 0 : }
237 :
238 : #ifdef SK_SUPPORT_LEGACY_PICTURE_GPUVETO
239 : 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.
249 0 : void SkPicture::SetPictureIOSecurityPrecautionsEnabled_Dangerous(bool set) {
250 0 : g_AllPictureIOSecurityPrecautionsEnabled = set;
251 0 : }
252 :
253 0 : bool SkPicture::PictureIOSecurityPrecautionsEnabled() {
254 0 : return g_AllPictureIOSecurityPrecautionsEnabled;
255 : }
|