1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2007 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkPicture.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkImageGenerator.h" 11cb93a386Sopenharmony_ci#include "include/core/SkPictureRecorder.h" 12cb93a386Sopenharmony_ci#include "include/core/SkSerialProcs.h" 13cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 14cb93a386Sopenharmony_ci#include "src/core/SkCanvasPriv.h" 15cb93a386Sopenharmony_ci#include "src/core/SkMathPriv.h" 16cb93a386Sopenharmony_ci#include "src/core/SkPictureCommon.h" 17cb93a386Sopenharmony_ci#include "src/core/SkPictureData.h" 18cb93a386Sopenharmony_ci#include "src/core/SkPicturePlayback.h" 19cb93a386Sopenharmony_ci#include "src/core/SkPicturePriv.h" 20cb93a386Sopenharmony_ci#include "src/core/SkPictureRecord.h" 21cb93a386Sopenharmony_ci#include "src/core/SkResourceCache.h" 22cb93a386Sopenharmony_ci#include <atomic> 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ci// When we read/write the SkPictInfo via a stream, we have a sentinel byte right after the info. 25cb93a386Sopenharmony_ci// Note: in the read/write buffer versions, we have a slightly different convention: 26cb93a386Sopenharmony_ci// We have a sentinel int32_t: 27cb93a386Sopenharmony_ci// 0 : failure 28cb93a386Sopenharmony_ci// 1 : PictureData 29cb93a386Sopenharmony_ci// <0 : -size of the custom data 30cb93a386Sopenharmony_cienum { 31cb93a386Sopenharmony_ci kFailure_TrailingStreamByteAfterPictInfo = 0, // nothing follows 32cb93a386Sopenharmony_ci kPictureData_TrailingStreamByteAfterPictInfo = 1, // SkPictureData follows 33cb93a386Sopenharmony_ci kCustom_TrailingStreamByteAfterPictInfo = 2, // -size32 follows 34cb93a386Sopenharmony_ci}; 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci/* SkPicture impl. This handles generic responsibilities like unique IDs and serialization. */ 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ciSkPicture::SkPicture() { 39cb93a386Sopenharmony_ci static std::atomic<uint32_t> nextID{1}; 40cb93a386Sopenharmony_ci do { 41cb93a386Sopenharmony_ci fUniqueID = nextID.fetch_add(+1, std::memory_order_relaxed); 42cb93a386Sopenharmony_ci } while (fUniqueID == 0); 43cb93a386Sopenharmony_ci} 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ciSkPicture::~SkPicture() { 46cb93a386Sopenharmony_ci if (fAddedToCache.load()) { 47cb93a386Sopenharmony_ci SkResourceCache::PostPurgeSharedID(SkPicturePriv::MakeSharedID(fUniqueID)); 48cb93a386Sopenharmony_ci } 49cb93a386Sopenharmony_ci} 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_cistatic const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' }; 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ciSkPictInfo SkPicture::createHeader() const { 54cb93a386Sopenharmony_ci SkPictInfo info; 55cb93a386Sopenharmony_ci // Copy magic bytes at the beginning of the header 56cb93a386Sopenharmony_ci static_assert(sizeof(kMagic) == 8, ""); 57cb93a386Sopenharmony_ci static_assert(sizeof(kMagic) == sizeof(info.fMagic), ""); 58cb93a386Sopenharmony_ci memcpy(info.fMagic, kMagic, sizeof(kMagic)); 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci // Set picture info after magic bytes in the header 61cb93a386Sopenharmony_ci info.setVersion(SkPicturePriv::kCurrent_Version); 62cb93a386Sopenharmony_ci info.fCullRect = this->cullRect(); 63cb93a386Sopenharmony_ci return info; 64cb93a386Sopenharmony_ci} 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_cibool SkPicture::IsValidPictInfo(const SkPictInfo& info) { 67cb93a386Sopenharmony_ci if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) { 68cb93a386Sopenharmony_ci return false; 69cb93a386Sopenharmony_ci } 70cb93a386Sopenharmony_ci if (info.getVersion() < SkPicturePriv::kMin_Version || 71cb93a386Sopenharmony_ci info.getVersion() > SkPicturePriv::kCurrent_Version) { 72cb93a386Sopenharmony_ci return false; 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci return true; 75cb93a386Sopenharmony_ci} 76cb93a386Sopenharmony_ci 77cb93a386Sopenharmony_cibool SkPicture::StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) { 78cb93a386Sopenharmony_ci if (!stream) { 79cb93a386Sopenharmony_ci return false; 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ci SkPictInfo info; 83cb93a386Sopenharmony_ci SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); 84cb93a386Sopenharmony_ci if (stream->read(&info.fMagic, sizeof(kMagic)) != sizeof(kMagic)) { 85cb93a386Sopenharmony_ci return false; 86cb93a386Sopenharmony_ci } 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci uint32_t version; 89cb93a386Sopenharmony_ci if (!stream->readU32(&version)) { return false; } 90cb93a386Sopenharmony_ci info.setVersion(version); 91cb93a386Sopenharmony_ci if (!stream->readScalar(&info.fCullRect.fLeft )) { return false; } 92cb93a386Sopenharmony_ci if (!stream->readScalar(&info.fCullRect.fTop )) { return false; } 93cb93a386Sopenharmony_ci if (!stream->readScalar(&info.fCullRect.fRight )) { return false; } 94cb93a386Sopenharmony_ci if (!stream->readScalar(&info.fCullRect.fBottom)) { return false; } 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci if (pInfo) { 97cb93a386Sopenharmony_ci *pInfo = info; 98cb93a386Sopenharmony_ci } 99cb93a386Sopenharmony_ci return IsValidPictInfo(info); 100cb93a386Sopenharmony_ci} 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_cibool SkPicture_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) { 103cb93a386Sopenharmony_ci return SkPicture::StreamIsSKP(stream, pInfo); 104cb93a386Sopenharmony_ci} 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_cibool SkPicture::BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo) { 107cb93a386Sopenharmony_ci SkPictInfo info; 108cb93a386Sopenharmony_ci SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); 109cb93a386Sopenharmony_ci if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) { 110cb93a386Sopenharmony_ci return false; 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci info.setVersion(buffer->readUInt()); 114cb93a386Sopenharmony_ci buffer->readRect(&info.fCullRect); 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci if (IsValidPictInfo(info)) { 117cb93a386Sopenharmony_ci if (pInfo) { *pInfo = info; } 118cb93a386Sopenharmony_ci return true; 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci return false; 121cb93a386Sopenharmony_ci} 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_cisk_sp<SkPicture> SkPicture::Forwardport(const SkPictInfo& info, 124cb93a386Sopenharmony_ci const SkPictureData* data, 125cb93a386Sopenharmony_ci SkReadBuffer* buffer) { 126cb93a386Sopenharmony_ci if (!data) { 127cb93a386Sopenharmony_ci return nullptr; 128cb93a386Sopenharmony_ci } 129cb93a386Sopenharmony_ci if (!data->opData()) { 130cb93a386Sopenharmony_ci return nullptr; 131cb93a386Sopenharmony_ci } 132cb93a386Sopenharmony_ci SkPicturePlayback playback(data); 133cb93a386Sopenharmony_ci SkPictureRecorder r; 134cb93a386Sopenharmony_ci playback.draw(r.beginRecording(info.fCullRect), nullptr/*no callback*/, buffer); 135cb93a386Sopenharmony_ci return r.finishRecordingAsPicture(); 136cb93a386Sopenharmony_ci} 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_cisk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, const SkDeserialProcs* procs) { 139cb93a386Sopenharmony_ci return MakeFromStream(stream, procs, nullptr); 140cb93a386Sopenharmony_ci} 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_cisk_sp<SkPicture> SkPicture::MakeFromData(const void* data, size_t size, 143cb93a386Sopenharmony_ci const SkDeserialProcs* procs) { 144cb93a386Sopenharmony_ci if (!data) { 145cb93a386Sopenharmony_ci return nullptr; 146cb93a386Sopenharmony_ci } 147cb93a386Sopenharmony_ci SkMemoryStream stream(data, size); 148cb93a386Sopenharmony_ci return MakeFromStream(&stream, procs, nullptr); 149cb93a386Sopenharmony_ci} 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_cisk_sp<SkPicture> SkPicture::MakeFromData(const SkData* data, const SkDeserialProcs* procs) { 152cb93a386Sopenharmony_ci if (!data) { 153cb93a386Sopenharmony_ci return nullptr; 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci SkMemoryStream stream(data->data(), data->size()); 156cb93a386Sopenharmony_ci return MakeFromStream(&stream, procs, nullptr); 157cb93a386Sopenharmony_ci} 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_cisk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, const SkDeserialProcs* procsPtr, 160cb93a386Sopenharmony_ci SkTypefacePlayback* typefaces) { 161cb93a386Sopenharmony_ci SkPictInfo info; 162cb93a386Sopenharmony_ci if (!StreamIsSKP(stream, &info)) { 163cb93a386Sopenharmony_ci return nullptr; 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci SkDeserialProcs procs; 167cb93a386Sopenharmony_ci if (procsPtr) { 168cb93a386Sopenharmony_ci procs = *procsPtr; 169cb93a386Sopenharmony_ci } 170cb93a386Sopenharmony_ci 171cb93a386Sopenharmony_ci uint8_t trailingStreamByteAfterPictInfo; 172cb93a386Sopenharmony_ci if (!stream->readU8(&trailingStreamByteAfterPictInfo)) { return nullptr; } 173cb93a386Sopenharmony_ci switch (trailingStreamByteAfterPictInfo) { 174cb93a386Sopenharmony_ci case kPictureData_TrailingStreamByteAfterPictInfo: { 175cb93a386Sopenharmony_ci std::unique_ptr<SkPictureData> data( 176cb93a386Sopenharmony_ci SkPictureData::CreateFromStream(stream, info, procs, typefaces)); 177cb93a386Sopenharmony_ci return Forwardport(info, data.get(), nullptr); 178cb93a386Sopenharmony_ci } 179cb93a386Sopenharmony_ci case kCustom_TrailingStreamByteAfterPictInfo: { 180cb93a386Sopenharmony_ci int32_t ssize; 181cb93a386Sopenharmony_ci if (!stream->readS32(&ssize) || ssize >= 0 || !procs.fPictureProc) { 182cb93a386Sopenharmony_ci return nullptr; 183cb93a386Sopenharmony_ci } 184cb93a386Sopenharmony_ci size_t size = sk_negate_to_size_t(ssize); 185cb93a386Sopenharmony_ci auto data = SkData::MakeUninitialized(size); 186cb93a386Sopenharmony_ci if (stream->read(data->writable_data(), size) != size) { 187cb93a386Sopenharmony_ci return nullptr; 188cb93a386Sopenharmony_ci } 189cb93a386Sopenharmony_ci return procs.fPictureProc(data->data(), size, procs.fPictureCtx); 190cb93a386Sopenharmony_ci } 191cb93a386Sopenharmony_ci default: // fall out to error return 192cb93a386Sopenharmony_ci break; 193cb93a386Sopenharmony_ci } 194cb93a386Sopenharmony_ci return nullptr; 195cb93a386Sopenharmony_ci} 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_cisk_sp<SkPicture> SkPicturePriv::MakeFromBuffer(SkReadBuffer& buffer) { 198cb93a386Sopenharmony_ci SkPictInfo info; 199cb93a386Sopenharmony_ci if (!SkPicture::BufferIsSKP(&buffer, &info)) { 200cb93a386Sopenharmony_ci return nullptr; 201cb93a386Sopenharmony_ci } 202cb93a386Sopenharmony_ci // size should be 0, 1, or negative 203cb93a386Sopenharmony_ci int32_t ssize = buffer.read32(); 204cb93a386Sopenharmony_ci if (ssize < 0) { 205cb93a386Sopenharmony_ci const SkDeserialProcs& procs = buffer.getDeserialProcs(); 206cb93a386Sopenharmony_ci if (!procs.fPictureProc) { 207cb93a386Sopenharmony_ci return nullptr; 208cb93a386Sopenharmony_ci } 209cb93a386Sopenharmony_ci size_t size = sk_negate_to_size_t(ssize); 210cb93a386Sopenharmony_ci return procs.fPictureProc(buffer.skip(size), size, procs.fPictureCtx); 211cb93a386Sopenharmony_ci } 212cb93a386Sopenharmony_ci if (ssize != 1) { 213cb93a386Sopenharmony_ci // 1 is the magic 'size' that means SkPictureData follows 214cb93a386Sopenharmony_ci return nullptr; 215cb93a386Sopenharmony_ci } 216cb93a386Sopenharmony_ci std::unique_ptr<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, info)); 217cb93a386Sopenharmony_ci return SkPicture::Forwardport(info, data.get(), &buffer); 218cb93a386Sopenharmony_ci} 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_ciSkPictureData* SkPicture::backport() const { 221cb93a386Sopenharmony_ci SkPictInfo info = this->createHeader(); 222cb93a386Sopenharmony_ci SkPictureRecord rec(info.fCullRect.roundOut(), 0/*flags*/); 223cb93a386Sopenharmony_ci rec.beginRecording(); 224cb93a386Sopenharmony_ci this->playback(&rec); 225cb93a386Sopenharmony_ci rec.endRecording(); 226cb93a386Sopenharmony_ci return new SkPictureData(rec, info); 227cb93a386Sopenharmony_ci} 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_civoid SkPicture::serialize(SkWStream* stream, const SkSerialProcs* procs) const { 230cb93a386Sopenharmony_ci this->serialize(stream, procs, nullptr); 231cb93a386Sopenharmony_ci} 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_cisk_sp<SkData> SkPicture::serialize(const SkSerialProcs* procs) const { 234cb93a386Sopenharmony_ci SkDynamicMemoryWStream stream; 235cb93a386Sopenharmony_ci this->serialize(&stream, procs, nullptr); 236cb93a386Sopenharmony_ci return stream.detachAsData(); 237cb93a386Sopenharmony_ci} 238cb93a386Sopenharmony_ci 239cb93a386Sopenharmony_cistatic sk_sp<SkData> custom_serialize(const SkPicture* picture, const SkSerialProcs& procs) { 240cb93a386Sopenharmony_ci if (procs.fPictureProc) { 241cb93a386Sopenharmony_ci auto data = procs.fPictureProc(const_cast<SkPicture*>(picture), procs.fPictureCtx); 242cb93a386Sopenharmony_ci if (data) { 243cb93a386Sopenharmony_ci size_t size = data->size(); 244cb93a386Sopenharmony_ci if (!SkTFitsIn<int32_t>(size) || size <= 1) { 245cb93a386Sopenharmony_ci return SkData::MakeEmpty(); 246cb93a386Sopenharmony_ci } 247cb93a386Sopenharmony_ci return data; 248cb93a386Sopenharmony_ci } 249cb93a386Sopenharmony_ci } 250cb93a386Sopenharmony_ci return nullptr; 251cb93a386Sopenharmony_ci} 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_cistatic bool write_pad32(SkWStream* stream, const void* data, size_t size) { 254cb93a386Sopenharmony_ci if (!stream->write(data, size)) { 255cb93a386Sopenharmony_ci return false; 256cb93a386Sopenharmony_ci } 257cb93a386Sopenharmony_ci if (size & 3) { 258cb93a386Sopenharmony_ci uint32_t zero = 0; 259cb93a386Sopenharmony_ci return stream->write(&zero, 4 - (size & 3)); 260cb93a386Sopenharmony_ci } 261cb93a386Sopenharmony_ci return true; 262cb93a386Sopenharmony_ci} 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_ci// Private serialize. 265cb93a386Sopenharmony_ci// SkPictureData::serialize makes a first pass on all subpictures, indicatewd by textBlobsOnly=true, 266cb93a386Sopenharmony_ci// to fill typefaceSet. 267cb93a386Sopenharmony_civoid SkPicture::serialize(SkWStream* stream, const SkSerialProcs* procsPtr, 268cb93a386Sopenharmony_ci SkRefCntSet* typefaceSet, bool textBlobsOnly) const { 269cb93a386Sopenharmony_ci SkSerialProcs procs; 270cb93a386Sopenharmony_ci if (procsPtr) { 271cb93a386Sopenharmony_ci procs = *procsPtr; 272cb93a386Sopenharmony_ci } 273cb93a386Sopenharmony_ci 274cb93a386Sopenharmony_ci SkPictInfo info = this->createHeader(); 275cb93a386Sopenharmony_ci stream->write(&info, sizeof(info)); 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ci if (auto custom = custom_serialize(this, procs)) { 278cb93a386Sopenharmony_ci int32_t size = SkToS32(custom->size()); 279cb93a386Sopenharmony_ci if (size == 0) { 280cb93a386Sopenharmony_ci stream->write8(kFailure_TrailingStreamByteAfterPictInfo); 281cb93a386Sopenharmony_ci return; 282cb93a386Sopenharmony_ci } 283cb93a386Sopenharmony_ci stream->write8(kCustom_TrailingStreamByteAfterPictInfo); 284cb93a386Sopenharmony_ci stream->write32(-size); // negative for custom format 285cb93a386Sopenharmony_ci write_pad32(stream, custom->data(), size); 286cb93a386Sopenharmony_ci return; 287cb93a386Sopenharmony_ci } 288cb93a386Sopenharmony_ci 289cb93a386Sopenharmony_ci std::unique_ptr<SkPictureData> data(this->backport()); 290cb93a386Sopenharmony_ci if (data) { 291cb93a386Sopenharmony_ci stream->write8(kPictureData_TrailingStreamByteAfterPictInfo); 292cb93a386Sopenharmony_ci data->serialize(stream, procs, typefaceSet, textBlobsOnly); 293cb93a386Sopenharmony_ci } else { 294cb93a386Sopenharmony_ci stream->write8(kFailure_TrailingStreamByteAfterPictInfo); 295cb93a386Sopenharmony_ci } 296cb93a386Sopenharmony_ci} 297cb93a386Sopenharmony_ci 298cb93a386Sopenharmony_civoid SkPicturePriv::Flatten(const sk_sp<const SkPicture> picture, SkWriteBuffer& buffer) { 299cb93a386Sopenharmony_ci SkPictInfo info = picture->createHeader(); 300cb93a386Sopenharmony_ci std::unique_ptr<SkPictureData> data(picture->backport()); 301cb93a386Sopenharmony_ci 302cb93a386Sopenharmony_ci buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic)); 303cb93a386Sopenharmony_ci buffer.writeUInt(info.getVersion()); 304cb93a386Sopenharmony_ci buffer.writeRect(info.fCullRect); 305cb93a386Sopenharmony_ci 306cb93a386Sopenharmony_ci if (auto custom = custom_serialize(picture.get(), buffer.fProcs)) { 307cb93a386Sopenharmony_ci int32_t size = SkToS32(custom->size()); 308cb93a386Sopenharmony_ci buffer.write32(-size); // negative for custom format 309cb93a386Sopenharmony_ci buffer.writePad32(custom->data(), size); 310cb93a386Sopenharmony_ci return; 311cb93a386Sopenharmony_ci } 312cb93a386Sopenharmony_ci 313cb93a386Sopenharmony_ci if (data) { 314cb93a386Sopenharmony_ci buffer.write32(1); // special size meaning SkPictureData 315cb93a386Sopenharmony_ci data->flatten(buffer); 316cb93a386Sopenharmony_ci } else { 317cb93a386Sopenharmony_ci buffer.write32(0); // signal no content 318cb93a386Sopenharmony_ci } 319cb93a386Sopenharmony_ci} 320cb93a386Sopenharmony_ci 321cb93a386Sopenharmony_cisk_sp<SkPicture> SkPicture::MakePlaceholder(SkRect cull) { 322cb93a386Sopenharmony_ci struct Placeholder : public SkPicture { 323cb93a386Sopenharmony_ci explicit Placeholder(SkRect cull) : fCull(cull) {} 324cb93a386Sopenharmony_ci 325cb93a386Sopenharmony_ci void playback(SkCanvas*, AbortCallback*) const override { } 326cb93a386Sopenharmony_ci 327cb93a386Sopenharmony_ci // approximateOpCount() needs to be greater than kMaxPictureOpsToUnrollInsteadOfRef 328cb93a386Sopenharmony_ci // (SkCanvasPriv.h) to avoid unrolling this into a parent picture. 329cb93a386Sopenharmony_ci int approximateOpCount(bool) const override { 330cb93a386Sopenharmony_ci return kMaxPictureOpsToUnrollInsteadOfRef+1; 331cb93a386Sopenharmony_ci } 332cb93a386Sopenharmony_ci size_t approximateBytesUsed() const override { return sizeof(*this); } 333cb93a386Sopenharmony_ci SkRect cullRect() const override { return fCull; } 334cb93a386Sopenharmony_ci 335cb93a386Sopenharmony_ci SkRect fCull; 336cb93a386Sopenharmony_ci }; 337cb93a386Sopenharmony_ci return sk_make_sp<Placeholder>(cull); 338cb93a386Sopenharmony_ci} 339