Home | History | Annotate | Download | only in core
      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