• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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