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 "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