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