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 26 SkPicture::SkPicture() : fUniqueID(0) {} 27 28 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 46 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 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 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 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 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 131 sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, SkImageDeserializer* factory) { 132 return MakeFromStream(stream, factory, nullptr); 133 } 134 135 sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream) { 136 SkImageDeserializer factory; 137 return MakeFromStream(stream, &factory); 138 } 139 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 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 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 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 174 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 183 void SkPicture::serialize(SkWStream* stream, SkPixelSerializer* pixelSerializer) const { 184 this->serialize(stream, pixelSerializer, nullptr); 185 } 186 187 sk_sp<SkData> SkPicture::serialize(SkPixelSerializer* pixelSerializer) const { 188 SkDynamicMemoryWStream stream; 189 this->serialize(&stream, pixelSerializer, nullptr); 190 return stream.detachAsData(); 191 } 192 193 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 208 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 225 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. 235 void SkPicture::SetPictureIOSecurityPrecautionsEnabled_Dangerous(bool set) { 236 g_AllPictureIOSecurityPrecautionsEnabled = set; 237 } 238 239 bool SkPicture::PictureIOSecurityPrecautionsEnabled() { 240 return g_AllPictureIOSecurityPrecautionsEnabled; 241 } 242