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 "SkImageGenerator.h" 10 #include "SkMathPriv.h" 11 #include "SkPicture.h" 12 #include "SkPictureCommon.h" 13 #include "SkPictureData.h" 14 #include "SkPicturePlayback.h" 15 #include "SkPictureRecord.h" 16 #include "SkPictureRecorder.h" 17 #include "SkSerialProcs.h" 18 19 // When we read/write the SkPictInfo via a stream, we have a sentinel byte right after the info. 20 // Note: in the read/write buffer versions, we have a slightly different convention: 21 // We have a sentinel int32_t: 22 // 0 : failure 23 // 1 : PictureData 24 // <0 : -size of the custom data 25 enum { 26 kFailure_TrailingStreamByteAfterPictInfo = 0, // nothing follows 27 kPictureData_TrailingStreamByteAfterPictInfo = 1, // SkPictureData follows 28 kCustom_TrailingStreamByteAfterPictInfo = 2, // -size32 follows 29 }; 30 31 /* SkPicture impl. This handles generic responsibilities like unique IDs and serialization. */ 32 33 SkPicture::SkPicture() : fUniqueID(0) {} 34 35 uint32_t SkPicture::uniqueID() const { 36 static uint32_t gNextID = 1; 37 uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed); 38 while (id == 0) { 39 uint32_t next = sk_atomic_fetch_add(&gNextID, 1u); 40 if (sk_atomic_compare_exchange(&fUniqueID, &id, next, 41 sk_memory_order_relaxed, 42 sk_memory_order_relaxed)) { 43 id = next; 44 } else { 45 // sk_atomic_compare_exchange replaced id with the current value of fUniqueID. 46 } 47 } 48 return id; 49 } 50 51 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' }; 52 53 SkPictInfo SkPicture::createHeader() const { 54 SkPictInfo info; 55 // Copy magic bytes at the beginning of the header 56 static_assert(sizeof(kMagic) == 8, ""); 57 static_assert(sizeof(kMagic) == sizeof(info.fMagic), ""); 58 memcpy(info.fMagic, kMagic, sizeof(kMagic)); 59 60 // Set picture info after magic bytes in the header 61 info.setVersion(CURRENT_PICTURE_VERSION); 62 info.fCullRect = this->cullRect(); 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::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 if (info.getVersion() < SkReadBuffer::kRemoveHeaderFlags_Version) { 93 (void)stream->readU32(); // used to be flags 94 } 95 96 if (IsValidPictInfo(info)) { 97 if (pInfo) { *pInfo = info; } 98 return true; 99 } 100 return false; 101 } 102 bool SkPicture_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) { 103 return SkPicture::StreamIsSKP(stream, pInfo); 104 } 105 106 bool SkPicture::BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo) { 107 SkPictInfo info; 108 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); 109 if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) { 110 return false; 111 } 112 113 info.setVersion(buffer->readUInt()); 114 buffer->readRect(&info.fCullRect); 115 if (info.getVersion() < SkReadBuffer::kRemoveHeaderFlags_Version) { 116 (void)buffer->readUInt(); // used to be flags 117 } 118 119 if (IsValidPictInfo(info)) { 120 if (pInfo) { *pInfo = info; } 121 return true; 122 } 123 return false; 124 } 125 126 sk_sp<SkPicture> SkPicture::Forwardport(const SkPictInfo& info, 127 const SkPictureData* data, 128 SkReadBuffer* buffer) { 129 if (!data) { 130 return nullptr; 131 } 132 if (!data->opData()) { 133 return nullptr; 134 } 135 SkPicturePlayback playback(data); 136 SkPictureRecorder r; 137 playback.draw(r.beginRecording(info.fCullRect), nullptr/*no callback*/, buffer); 138 return r.finishRecordingAsPicture(); 139 } 140 141 sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, const SkDeserialProcs* procs) { 142 return MakeFromStream(stream, procs, nullptr); 143 } 144 145 sk_sp<SkPicture> SkPicture::MakeFromData(const void* data, size_t size, 146 const SkDeserialProcs* procs) { 147 if (!data) { 148 return nullptr; 149 } 150 SkMemoryStream stream(data, size); 151 return MakeFromStream(&stream, procs, nullptr); 152 } 153 154 sk_sp<SkPicture> SkPicture::MakeFromData(const SkData* data, const SkDeserialProcs* procs) { 155 if (!data) { 156 return nullptr; 157 } 158 SkMemoryStream stream(data->data(), data->size()); 159 return MakeFromStream(&stream, procs, nullptr); 160 } 161 162 sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, const SkDeserialProcs* procsPtr, 163 SkTypefacePlayback* typefaces) { 164 SkPictInfo info; 165 if (!StreamIsSKP(stream, &info)) { 166 return nullptr; 167 } 168 169 SkDeserialProcs procs; 170 if (procsPtr) { 171 procs = *procsPtr; 172 } 173 174 switch (stream->readU8()) { 175 case kPictureData_TrailingStreamByteAfterPictInfo: { 176 std::unique_ptr<SkPictureData> data( 177 SkPictureData::CreateFromStream(stream, info, procs, typefaces)); 178 return Forwardport(info, data.get(), nullptr); 179 } 180 case kCustom_TrailingStreamByteAfterPictInfo: { 181 int32_t ssize = stream->readS32(); 182 if (ssize >= 0 || !procs.fPictureProc) { 183 return nullptr; 184 } 185 size_t size = sk_negate_to_size_t(ssize); 186 auto data = SkData::MakeUninitialized(size); 187 if (stream->read(data->writable_data(), size) != size) { 188 return nullptr; 189 } 190 return procs.fPictureProc(data->data(), size, procs.fPictureCtx); 191 } 192 default: // fall through to error return 193 break; 194 } 195 return nullptr; 196 } 197 198 sk_sp<SkPicture> SkPicture::MakeFromBuffer(SkReadBuffer& buffer) { 199 SkPictInfo info; 200 if (!BufferIsSKP(&buffer, &info)) { 201 return nullptr; 202 } 203 // size should be 0, 1, or negative 204 int32_t ssize = buffer.read32(); 205 if (ssize < 0) { 206 const SkDeserialProcs& procs = buffer.fProcs; 207 if (!procs.fPictureProc) { 208 return nullptr; 209 } 210 size_t size = sk_negate_to_size_t(ssize); 211 return procs.fPictureProc(buffer.skip(size), size, procs.fPictureCtx); 212 } 213 if (ssize != 1) { 214 // 1 is the magic 'size' that means SkPictureData follows 215 return nullptr; 216 } 217 std::unique_ptr<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, info)); 218 return Forwardport(info, data.get(), &buffer); 219 } 220 221 SkPictureData* SkPicture::backport() const { 222 SkPictInfo info = this->createHeader(); 223 SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.height()), 0/*flags*/); 224 rec.beginRecording(); 225 this->playback(&rec); 226 rec.endRecording(); 227 return new SkPictureData(rec, info); 228 } 229 230 void SkPicture::serialize(SkWStream* stream, const SkSerialProcs* procs) const { 231 this->serialize(stream, procs, nullptr); 232 } 233 234 sk_sp<SkData> SkPicture::serialize(const SkSerialProcs* procs) const { 235 SkDynamicMemoryWStream stream; 236 this->serialize(&stream, procs, nullptr); 237 return stream.detachAsData(); 238 } 239 240 static sk_sp<SkData> custom_serialize(const SkPicture* picture, const SkSerialProcs& procs) { 241 if (procs.fPictureProc) { 242 auto data = procs.fPictureProc(const_cast<SkPicture*>(picture), procs.fPictureCtx); 243 if (data) { 244 size_t size = data->size(); 245 if (!sk_64_isS32(size) || size <= 1) { 246 return SkData::MakeEmpty(); 247 } 248 return data; 249 } 250 } 251 return nullptr; 252 } 253 254 static bool write_pad32(SkWStream* stream, const void* data, size_t size) { 255 if (!stream->write(data, size)) { 256 return false; 257 } 258 if (size & 3) { 259 uint32_t zero = 0; 260 return stream->write(&zero, 4 - (size & 3)); 261 } 262 return true; 263 } 264 265 void SkPicture::serialize(SkWStream* stream, const SkSerialProcs* procsPtr, 266 SkRefCntSet* typefaceSet) const { 267 SkSerialProcs procs; 268 if (procsPtr) { 269 procs = *procsPtr; 270 } 271 272 SkPictInfo info = this->createHeader(); 273 stream->write(&info, sizeof(info)); 274 275 if (auto custom = custom_serialize(this, procs)) { 276 int32_t size = SkToS32(custom->size()); 277 if (size == 0) { 278 stream->write8(kFailure_TrailingStreamByteAfterPictInfo); 279 return; 280 } 281 stream->write8(kCustom_TrailingStreamByteAfterPictInfo); 282 stream->write32(-size); // negative for custom format 283 write_pad32(stream, custom->data(), size); 284 return; 285 } 286 287 std::unique_ptr<SkPictureData> data(this->backport()); 288 if (data) { 289 stream->write8(kPictureData_TrailingStreamByteAfterPictInfo); 290 data->serialize(stream, procs, typefaceSet); 291 } else { 292 stream->write8(kFailure_TrailingStreamByteAfterPictInfo); 293 } 294 } 295 296 void SkPicture::flatten(SkWriteBuffer& buffer) const { 297 SkPictInfo info = this->createHeader(); 298 std::unique_ptr<SkPictureData> data(this->backport()); 299 300 buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic)); 301 buffer.writeUInt(info.getVersion()); 302 buffer.writeRect(info.fCullRect); 303 304 if (auto custom = custom_serialize(this, buffer.fProcs)) { 305 int32_t size = SkToS32(custom->size()); 306 buffer.write32(-size); // negative for custom format 307 buffer.writePad32(custom->data(), size); 308 return; 309 } 310 311 if (data) { 312 buffer.write32(1); // special size meaning SkPictureData 313 data->flatten(buffer); 314 } else { 315 buffer.write32(0); // signal no content 316 } 317 } 318 319 sk_sp<SkPicture> SkPicture::MakePlaceholder(SkRect cull) { 320 struct Placeholder : public SkPicture { 321 explicit Placeholder(SkRect cull) : fCull(cull) {} 322 323 void playback(SkCanvas*, AbortCallback*) const override { } 324 325 // approximateOpCount() needs to be greater than kMaxPictureOpsToUnrollInsteadOfRef 326 // in SkCanvas.cpp to avoid that unrolling. SK_MaxS32 can't not be big enough! 327 int approximateOpCount() const override { return SK_MaxS32; } 328 size_t approximateBytesUsed() const override { return sizeof(*this); } 329 SkRect cullRect() const override { return fCull; } 330 331 SkRect fCull; 332 }; 333 return sk_make_sp<Placeholder>(cull); 334 } 335