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 "SkMessageBus.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 DECLARE_SKMESSAGEBUS_MESSAGE(SkPicture::DeletionMessage); 25 26 /* SkPicture impl. This handles generic responsibilities like unique IDs and serialization. */ 27 28 SkPicture::SkPicture() : fUniqueID(0) {} 29 30 SkPicture::~SkPicture() { 31 // TODO: move this to ~SkBigPicture() only? 32 33 // If the ID is still zero, no one has read it, so no need to send this message. 34 uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed); 35 if (id != 0) { 36 SkPicture::DeletionMessage msg = { (int32_t)id }; 37 SkMessageBus<SkPicture::DeletionMessage>::Post(msg); 38 } 39 } 40 41 uint32_t SkPicture::uniqueID() const { 42 static uint32_t gNextID = 1; 43 uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed); 44 while (id == 0) { 45 uint32_t next = sk_atomic_fetch_add(&gNextID, 1u); 46 if (sk_atomic_compare_exchange(&fUniqueID, &id, next, 47 sk_memory_order_relaxed, 48 sk_memory_order_relaxed)) { 49 id = next; 50 } else { 51 // sk_atomic_compare_exchange replaced id with the current value of fUniqueID. 52 } 53 } 54 return id; 55 } 56 57 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' }; 58 59 SkPictInfo SkPicture::createHeader() const { 60 SkPictInfo info; 61 // Copy magic bytes at the beginning of the header 62 static_assert(sizeof(kMagic) == 8, ""); 63 static_assert(sizeof(kMagic) == sizeof(info.fMagic), ""); 64 memcpy(info.fMagic, kMagic, sizeof(kMagic)); 65 66 // Set picture info after magic bytes in the header 67 info.fVersion = CURRENT_PICTURE_VERSION; 68 info.fCullRect = this->cullRect(); 69 info.fFlags = SkPictInfo::kCrossProcess_Flag; 70 // TODO: remove this flag, since we're always float (now) 71 info.fFlags |= SkPictInfo::kScalarIsFloat_Flag; 72 73 if (8 == sizeof(void*)) { 74 info.fFlags |= SkPictInfo::kPtrIs64Bit_Flag; 75 } 76 return info; 77 } 78 79 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) { 80 if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) { 81 return false; 82 } 83 if (info.fVersion < MIN_PICTURE_VERSION || info.fVersion > CURRENT_PICTURE_VERSION) { 84 return false; 85 } 86 return true; 87 } 88 89 bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) { 90 if (!stream) { 91 return false; 92 } 93 94 SkPictInfo info; 95 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); 96 if (!stream->read(&info.fMagic, sizeof(kMagic))) { 97 return false; 98 } 99 100 info.fVersion = stream->readU32(); 101 info.fCullRect.fLeft = stream->readScalar(); 102 info.fCullRect.fTop = stream->readScalar(); 103 info.fCullRect.fRight = stream->readScalar(); 104 info.fCullRect.fBottom = stream->readScalar(); 105 info.fFlags = stream->readU32(); 106 107 if (IsValidPictInfo(info)) { 108 if (pInfo) { *pInfo = info; } 109 return true; 110 } 111 return false; 112 } 113 114 bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo) { 115 SkPictInfo info; 116 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); 117 if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) { 118 return false; 119 } 120 121 info.fVersion = buffer->readUInt(); 122 buffer->readRect(&info.fCullRect); 123 info.fFlags = buffer->readUInt(); 124 125 if (IsValidPictInfo(info)) { 126 if (pInfo) { *pInfo = info; } 127 return true; 128 } 129 return false; 130 } 131 132 SkPicture* SkPicture::Forwardport(const SkPictInfo& info, const SkPictureData* data) { 133 if (!data) { 134 return nullptr; 135 } 136 SkPicturePlayback playback(data); 137 SkPictureRecorder r; 138 playback.draw(r.beginRecording(info.fCullRect), nullptr/*no callback*/); 139 return r.endRecording(); 140 } 141 142 static bool default_install(const void* src, size_t length, SkBitmap* dst) { 143 SkAutoTUnref<SkData> encoded(SkData::NewWithCopy(src, length)); 144 return encoded && SkDEPRECATED_InstallDiscardablePixelRef( 145 SkImageGenerator::NewFromEncoded(encoded), dst); 146 } 147 148 SkPicture* SkPicture::CreateFromStream(SkStream* stream) { 149 return CreateFromStream(stream, &default_install, nullptr); 150 } 151 152 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc proc) { 153 return CreateFromStream(stream, proc, nullptr); 154 } 155 156 SkPicture* SkPicture::CreateFromStream(SkStream* stream, 157 InstallPixelRefProc proc, 158 SkTypefacePlayback* typefaces) { 159 SkPictInfo info; 160 if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) { 161 return nullptr; 162 } 163 SkAutoTDelete<SkPictureData> data( 164 SkPictureData::CreateFromStream(stream, info, proc, typefaces)); 165 return Forwardport(info, data); 166 } 167 168 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) { 169 SkPictInfo info; 170 if (!InternalOnly_BufferIsSKP(&buffer, &info) || !buffer.readBool()) { 171 return nullptr; 172 } 173 SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, info)); 174 return Forwardport(info, data); 175 } 176 177 SkPictureData* SkPicture::backport() const { 178 SkPictInfo info = this->createHeader(); 179 SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.height()), 0/*flags*/); 180 rec.beginRecording(); 181 this->playback(&rec); 182 rec.endRecording(); 183 return new SkPictureData(rec, info, false /*deep copy ops?*/); 184 } 185 186 void SkPicture::serialize(SkWStream* stream, SkPixelSerializer* pixelSerializer) const { 187 this->serialize(stream, pixelSerializer, nullptr); 188 } 189 190 void SkPicture::serialize(SkWStream* stream, 191 SkPixelSerializer* pixelSerializer, 192 SkRefCntSet* typefaceSet) const { 193 SkPictInfo info = this->createHeader(); 194 SkAutoTDelete<SkPictureData> data(this->backport()); 195 196 stream->write(&info, sizeof(info)); 197 if (data) { 198 stream->writeBool(true); 199 data->serialize(stream, pixelSerializer, typefaceSet); 200 } else { 201 stream->writeBool(false); 202 } 203 } 204 205 void SkPicture::flatten(SkWriteBuffer& buffer) const { 206 SkPictInfo info = this->createHeader(); 207 SkAutoTDelete<SkPictureData> data(this->backport()); 208 209 buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic)); 210 buffer.writeUInt(info.fVersion); 211 buffer.writeRect(info.fCullRect); 212 buffer.writeUInt(info.fFlags); 213 if (data) { 214 buffer.writeBool(true); 215 data->flatten(buffer); 216 } else { 217 buffer.writeBool(false); 218 } 219 } 220 221 bool SkPicture::suitableForGpuRasterization(GrContext*, const char** whyNot) const { 222 if (this->numSlowPaths() > 5) { 223 if (whyNot) { *whyNot = "Too many slow paths (either concave or dashed)."; } 224 return false; 225 } 226 return true; 227 } 228 229 // Global setting to disable security precautions for serialization. 230 void SkPicture::SetPictureIOSecurityPrecautionsEnabled_Dangerous(bool set) { 231 g_AllPictureIOSecurityPrecautionsEnabled = set; 232 } 233 234 bool SkPicture::PictureIOSecurityPrecautionsEnabled() { 235 return g_AllPictureIOSecurityPrecautionsEnabled; 236 } 237