LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkPictureData.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 386 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 41 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2011 Google Inc.
       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 <new>
       9             : 
      10             : #include "SkAutoMalloc.h"
      11             : #include "SkImageGenerator.h"
      12             : #include "SkPictureData.h"
      13             : #include "SkPictureRecord.h"
      14             : #include "SkReadBuffer.h"
      15             : #include "SkTextBlob.h"
      16             : #include "SkTypeface.h"
      17             : #include "SkWriteBuffer.h"
      18             : 
      19             : #if SK_SUPPORT_GPU
      20             : #include "GrContext.h"
      21             : #endif
      22             : 
      23             : template <typename T> int SafeCount(const T* obj) {
      24             :     return obj ? obj->count() : 0;
      25             : }
      26             : 
      27           0 : SkPictureData::SkPictureData(const SkPictInfo& info)
      28           0 :     : fInfo(info) {
      29           0 :     this->init();
      30           0 : }
      31             : 
      32           0 : void SkPictureData::initForPlayback() const {
      33             :     // ensure that the paths bounds are pre-computed
      34           0 :     for (int i = 0; i < fPaths.count(); i++) {
      35           0 :         fPaths[i].updateBoundsCache();
      36             :     }
      37           0 : }
      38             : 
      39           0 : SkPictureData::SkPictureData(const SkPictureRecord& record,
      40           0 :                              const SkPictInfo& info)
      41           0 :     : fInfo(info) {
      42             : 
      43           0 :     this->init();
      44             : 
      45           0 :     fOpData = record.opData();
      46             : 
      47           0 :     fContentInfo.set(record.fContentInfo);
      48             : 
      49           0 :     fPaints  = record.fPaints;
      50             : 
      51           0 :     fPaths.reset(record.fPaths.count());
      52           0 :     record.fPaths.foreach([this](const SkPath& path, int n) {
      53             :         // These indices are logically 1-based, but we need to serialize them
      54             :         // 0-based to keep the deserializing SkPictureData::getPath() working.
      55           0 :         fPaths[n-1] = path;
      56           0 :     });
      57             : 
      58           0 :     this->initForPlayback();
      59             : 
      60           0 :     const SkTDArray<const SkPicture* >& pictures = record.getPictureRefs();
      61           0 :     fPictureCount = pictures.count();
      62           0 :     if (fPictureCount > 0) {
      63           0 :         fPictureRefs = new const SkPicture* [fPictureCount];
      64           0 :         for (int i = 0; i < fPictureCount; i++) {
      65           0 :             fPictureRefs[i] = pictures[i];
      66           0 :             fPictureRefs[i]->ref();
      67             :         }
      68             :     }
      69             : 
      70           0 :     const SkTDArray<SkDrawable* >& drawables = record.getDrawableRefs();
      71           0 :     fDrawableCount = drawables.count();
      72           0 :     if (fDrawableCount > 0) {
      73           0 :         fDrawableRefs = new SkDrawable* [fDrawableCount];
      74           0 :         for (int i = 0; i < fDrawableCount; i++) {
      75           0 :             fDrawableRefs[i] = drawables[i];
      76           0 :             fDrawableRefs[i]->ref();
      77             :         }
      78             :     }
      79             : 
      80             :     // templatize to consolidate with similar picture logic?
      81           0 :     const SkTDArray<const SkTextBlob*>& blobs = record.getTextBlobRefs();
      82           0 :     fTextBlobCount = blobs.count();
      83           0 :     if (fTextBlobCount > 0) {
      84           0 :         fTextBlobRefs = new const SkTextBlob* [fTextBlobCount];
      85           0 :         for (int i = 0; i < fTextBlobCount; ++i) {
      86           0 :             fTextBlobRefs[i] = SkRef(blobs[i]);
      87             :         }
      88             :     }
      89             : 
      90           0 :     const SkTDArray<const SkVertices*>& verts = record.getVerticesRefs();
      91           0 :     fVerticesCount = verts.count();
      92           0 :     if (fVerticesCount > 0) {
      93           0 :         fVerticesRefs = new const SkVertices* [fVerticesCount];
      94           0 :         for (int i = 0; i < fVerticesCount; ++i) {
      95           0 :             fVerticesRefs[i] = SkRef(verts[i]);
      96             :         }
      97             :     }
      98             :     
      99           0 :     const SkTDArray<const SkImage*>& imgs = record.getImageRefs();
     100           0 :     fImageCount = imgs.count();
     101           0 :     if (fImageCount > 0) {
     102           0 :         fImageRefs = new const SkImage* [fImageCount];
     103           0 :         for (int i = 0; i < fImageCount; ++i) {
     104           0 :             fImageRefs[i] = SkRef(imgs[i]);
     105             :         }
     106             :     }
     107           0 : }
     108             : 
     109           0 : void SkPictureData::init() {
     110           0 :     fPictureRefs = nullptr;
     111           0 :     fPictureCount = 0;
     112           0 :     fDrawableRefs = nullptr;
     113           0 :     fDrawableCount = 0;
     114           0 :     fTextBlobRefs = nullptr;
     115           0 :     fTextBlobCount = 0;
     116           0 :     fVerticesRefs = nullptr;
     117           0 :     fVerticesCount = 0;
     118           0 :     fImageRefs = nullptr;
     119           0 :     fImageCount = 0;
     120           0 :     fFactoryPlayback = nullptr;
     121           0 : }
     122             : 
     123           0 : SkPictureData::~SkPictureData() {
     124           0 :     for (int i = 0; i < fPictureCount; i++) {
     125           0 :         fPictureRefs[i]->unref();
     126             :     }
     127           0 :     delete[] fPictureRefs;
     128             : 
     129           0 :     for (int i = 0; i < fDrawableCount; i++) {
     130           0 :         fDrawableRefs[i]->unref();
     131             :     }
     132           0 :     if (fDrawableCount > 0) {
     133           0 :         SkASSERT(fDrawableRefs);
     134           0 :         delete[] fDrawableRefs;
     135             :     }
     136             : 
     137           0 :     for (int i = 0; i < fTextBlobCount; i++) {
     138           0 :         fTextBlobRefs[i]->unref();
     139             :     }
     140           0 :     delete[] fTextBlobRefs;
     141             : 
     142           0 :     for (int i = 0; i < fVerticesCount; i++) {
     143           0 :         fVerticesRefs[i]->unref();
     144             :     }
     145           0 :     delete[] fVerticesRefs;
     146             : 
     147           0 :     for (int i = 0; i < fImageCount; i++) {
     148           0 :         fImageRefs[i]->unref();
     149             :     }
     150           0 :     delete[] fImageRefs;
     151             : 
     152           0 :     delete fFactoryPlayback;
     153           0 : }
     154             : 
     155           0 : bool SkPictureData::containsBitmaps() const {
     156           0 :     if (fBitmapImageCount > 0 || fImageCount > 0) {
     157           0 :         return true;
     158             :     }
     159           0 :     for (int i = 0; i < fPictureCount; ++i) {
     160           0 :         if (fPictureRefs[i]->willPlayBackBitmaps()) {
     161           0 :             return true;
     162             :         }
     163             :     }
     164           0 :     return false;
     165             : }
     166             : 
     167             : ///////////////////////////////////////////////////////////////////////////////
     168             : ///////////////////////////////////////////////////////////////////////////////
     169             : 
     170             : #include "SkStream.h"
     171             : 
     172           0 : static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
     173           0 :     size_t size = 4;  // for 'count'
     174             : 
     175           0 :     for (int i = 0; i < count; i++) {
     176           0 :         const char* name = SkFlattenable::FactoryToName(array[i]);
     177           0 :         if (nullptr == name || 0 == *name) {
     178           0 :             size += SkWStream::SizeOfPackedUInt(0);
     179             :         } else {
     180           0 :             size_t len = strlen(name);
     181           0 :             size += SkWStream::SizeOfPackedUInt(len);
     182           0 :             size += len;
     183             :         }
     184             :     }
     185             : 
     186           0 :     return size;
     187             : }
     188             : 
     189           0 : static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, size_t size) {
     190           0 :     buffer.writeUInt(tag);
     191           0 :     buffer.writeUInt(SkToU32(size));
     192           0 : }
     193             : 
     194           0 : static void write_tag_size(SkWStream* stream, uint32_t tag, size_t size) {
     195           0 :     stream->write32(tag);
     196           0 :     stream->write32(SkToU32(size));
     197           0 : }
     198             : 
     199           0 : void SkPictureData::WriteFactories(SkWStream* stream, const SkFactorySet& rec) {
     200           0 :     int count = rec.count();
     201             : 
     202           0 :     SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
     203           0 :     SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
     204           0 :     rec.copyToArray(array);
     205             : 
     206           0 :     size_t size = compute_chunk_size(array, count);
     207             : 
     208             :     // TODO: write_tag_size should really take a size_t
     209           0 :     write_tag_size(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
     210           0 :     SkDEBUGCODE(size_t start = stream->bytesWritten());
     211           0 :     stream->write32(count);
     212             : 
     213           0 :     for (int i = 0; i < count; i++) {
     214           0 :         const char* name = SkFlattenable::FactoryToName(array[i]);
     215           0 :         if (nullptr == name || 0 == *name) {
     216           0 :             stream->writePackedUInt(0);
     217             :         } else {
     218           0 :             size_t len = strlen(name);
     219           0 :             stream->writePackedUInt(len);
     220           0 :             stream->write(name, len);
     221             :         }
     222             :     }
     223             : 
     224           0 :     SkASSERT(size == (stream->bytesWritten() - start));
     225           0 : }
     226             : 
     227           0 : void SkPictureData::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
     228           0 :     int count = rec.count();
     229             : 
     230           0 :     write_tag_size(stream, SK_PICT_TYPEFACE_TAG, count);
     231             : 
     232           0 :     SkAutoSTMalloc<16, SkTypeface*> storage(count);
     233           0 :     SkTypeface** array = (SkTypeface**)storage.get();
     234           0 :     rec.copyToArray((SkRefCnt**)array);
     235             : 
     236           0 :     for (int i = 0; i < count; i++) {
     237           0 :         array[i]->serialize(stream);
     238             :     }
     239           0 : }
     240             : 
     241           0 : void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
     242             :     int i, n;
     243             : 
     244           0 :     if ((n = fPaints.count()) > 0) {
     245           0 :         write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
     246           0 :         for (i = 0; i < n; i++) {
     247           0 :             buffer.writePaint(fPaints[i]);
     248             :         }
     249             :     }
     250             : 
     251           0 :     if ((n = fPaths.count()) > 0) {
     252           0 :         write_tag_size(buffer, SK_PICT_PATH_BUFFER_TAG, n);
     253           0 :         buffer.writeInt(n);
     254           0 :         for (int i = 0; i < n; i++) {
     255           0 :             buffer.writePath(fPaths[i]);
     256             :         }
     257             :     }
     258             : 
     259           0 :     if (fTextBlobCount > 0) {
     260           0 :         write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobCount);
     261           0 :         for (i = 0; i  < fTextBlobCount; ++i) {
     262           0 :             fTextBlobRefs[i]->flatten(buffer);
     263             :         }
     264             :     }
     265             : 
     266           0 :     if (fVerticesCount > 0) {
     267           0 :         write_tag_size(buffer, SK_PICT_VERTICES_BUFFER_TAG, fVerticesCount);
     268           0 :         for (i = 0; i  < fVerticesCount; ++i) {
     269           0 :             buffer.writeDataAsByteArray(fVerticesRefs[i]->encode().get());
     270             :         }
     271             :     }
     272             : 
     273           0 :     if (fImageCount > 0) {
     274           0 :         write_tag_size(buffer, SK_PICT_IMAGE_BUFFER_TAG, fImageCount);
     275           0 :         for (i = 0; i  < fImageCount; ++i) {
     276           0 :             buffer.writeImage(fImageRefs[i]);
     277             :         }
     278             :     }
     279           0 : }
     280             : 
     281           0 : void SkPictureData::serialize(SkWStream* stream,
     282             :                               SkPixelSerializer* pixelSerializer,
     283             :                               SkRefCntSet* topLevelTypeFaceSet) const {
     284             :     // This can happen at pretty much any time, so might as well do it first.
     285           0 :     write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size());
     286           0 :     stream->write(fOpData->bytes(), fOpData->size());
     287             : 
     288             :     // We serialize all typefaces into the typeface section of the top-level picture.
     289           0 :     SkRefCntSet localTypefaceSet;
     290           0 :     SkRefCntSet* typefaceSet = topLevelTypeFaceSet ? topLevelTypeFaceSet : &localTypefaceSet;
     291             : 
     292             :     // We delay serializing the bulk of our data until after we've serialized
     293             :     // factories and typefaces by first serializing to an in-memory write buffer.
     294           0 :     SkFactorySet factSet;  // buffer refs factSet, so factSet must come first.
     295           0 :     SkBinaryWriteBuffer buffer(SkBinaryWriteBuffer::kCrossProcess_Flag);
     296           0 :     buffer.setFactoryRecorder(&factSet);
     297           0 :     buffer.setPixelSerializer(sk_ref_sp(pixelSerializer));
     298           0 :     buffer.setTypefaceRecorder(typefaceSet);
     299           0 :     this->flattenToBuffer(buffer);
     300             : 
     301             :     // Dummy serialize our sub-pictures for the side effect of filling
     302             :     // typefaceSet with typefaces from sub-pictures.
     303           0 :     struct DevNull: public SkWStream {
     304           0 :         DevNull() : fBytesWritten(0) {}
     305             :         size_t fBytesWritten;
     306           0 :         bool write(const void*, size_t size) override { fBytesWritten += size; return true; }
     307           0 :         size_t bytesWritten() const override { return fBytesWritten; }
     308           0 :     } devnull;
     309           0 :     for (int i = 0; i < fPictureCount; i++) {
     310           0 :         fPictureRefs[i]->serialize(&devnull, pixelSerializer, typefaceSet);
     311             :     }
     312             : 
     313             :     // We need to write factories before we write the buffer.
     314             :     // We need to write typefaces before we write the buffer or any sub-picture.
     315           0 :     WriteFactories(stream, factSet);
     316           0 :     if (typefaceSet == &localTypefaceSet) {
     317           0 :         WriteTypefaces(stream, *typefaceSet);
     318             :     }
     319             : 
     320             :     // Write the buffer.
     321           0 :     write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
     322           0 :     buffer.writeToStream(stream);
     323             : 
     324             :     // Write sub-pictures by calling serialize again.
     325           0 :     if (fPictureCount > 0) {
     326           0 :         write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
     327           0 :         for (int i = 0; i < fPictureCount; i++) {
     328           0 :             fPictureRefs[i]->serialize(stream, pixelSerializer, typefaceSet);
     329             :         }
     330             :     }
     331             : 
     332           0 :     stream->write32(SK_PICT_EOF_TAG);
     333           0 : }
     334             : 
     335           0 : void SkPictureData::flatten(SkWriteBuffer& buffer) const {
     336           0 :     write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size());
     337           0 :     buffer.writeByteArray(fOpData->bytes(), fOpData->size());
     338             : 
     339           0 :     if (fPictureCount > 0) {
     340           0 :         write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictureCount);
     341           0 :         for (int i = 0; i < fPictureCount; i++) {
     342           0 :             fPictureRefs[i]->flatten(buffer);
     343             :         }
     344             :     }
     345             : 
     346           0 :     if (fDrawableCount > 0) {
     347           0 :         write_tag_size(buffer, SK_PICT_DRAWABLE_TAG, fDrawableCount);
     348           0 :         for (int i = 0; i < fDrawableCount; i++) {
     349           0 :             buffer.writeFlattenable(fDrawableRefs[i]);
     350             :         }
     351             :     }
     352             : 
     353             :     // Write this picture playback's data into a writebuffer
     354           0 :     this->flattenToBuffer(buffer);
     355           0 :     buffer.write32(SK_PICT_EOF_TAG);
     356           0 : }
     357             : 
     358             : ///////////////////////////////////////////////////////////////////////////////
     359             : 
     360             : /**
     361             :  *  Return the corresponding SkReadBuffer flags, given a set of
     362             :  *  SkPictInfo flags.
     363             :  */
     364           0 : static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
     365             :     static const struct {
     366             :         uint32_t    fSrc;
     367             :         uint32_t    fDst;
     368             :     } gSD[] = {
     369             :         { SkPictInfo::kCrossProcess_Flag,   SkReadBuffer::kCrossProcess_Flag },
     370             :         { SkPictInfo::kScalarIsFloat_Flag,  SkReadBuffer::kScalarIsFloat_Flag },
     371             :         { SkPictInfo::kPtrIs64Bit_Flag,     SkReadBuffer::kPtrIs64Bit_Flag },
     372             :     };
     373             : 
     374           0 :     uint32_t rbMask = 0;
     375           0 :     for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) {
     376           0 :         if (pictInfoFlags & gSD[i].fSrc) {
     377           0 :             rbMask |= gSD[i].fDst;
     378             :         }
     379             :     }
     380           0 :     return rbMask;
     381             : }
     382             : 
     383           0 : bool SkPictureData::parseStreamTag(SkStream* stream,
     384             :                                    uint32_t tag,
     385             :                                    uint32_t size,
     386             :                                    SkImageDeserializer* factory,
     387             :                                    SkTypefacePlayback* topLevelTFPlayback) {
     388             :     /*
     389             :      *  By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
     390             :      *  its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
     391             :      *  but if they are present, they need to have been seen before the buffer.
     392             :      *
     393             :      *  We assert that if/when we see either of these, that we have not yet seen
     394             :      *  the buffer tag, because if we have, then its too-late to deal with the
     395             :      *  factories or typefaces.
     396             :      */
     397           0 :     SkDEBUGCODE(bool haveBuffer = false;)
     398             : 
     399           0 :     switch (tag) {
     400             :         case SK_PICT_READER_TAG:
     401           0 :             SkASSERT(nullptr == fOpData);
     402           0 :             fOpData = SkData::MakeFromStream(stream, size);
     403           0 :             if (!fOpData) {
     404           0 :                 return false;
     405             :             }
     406           0 :             break;
     407             :         case SK_PICT_FACTORY_TAG: {
     408           0 :             SkASSERT(!haveBuffer);
     409           0 :             size = stream->readU32();
     410           0 :             fFactoryPlayback = new SkFactoryPlayback(size);
     411           0 :             for (size_t i = 0; i < size; i++) {
     412           0 :                 SkString str;
     413           0 :                 const size_t len = stream->readPackedUInt();
     414           0 :                 str.resize(len);
     415           0 :                 if (stream->read(str.writable_str(), len) != len) {
     416           0 :                     return false;
     417             :                 }
     418           0 :                 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
     419             :             }
     420           0 :         } break;
     421             :         case SK_PICT_TYPEFACE_TAG: {
     422           0 :             SkASSERT(!haveBuffer);
     423           0 :             const int count = SkToInt(size);
     424           0 :             fTFPlayback.setCount(count);
     425           0 :             for (int i = 0; i < count; i++) {
     426           0 :                 sk_sp<SkTypeface> tf(SkTypeface::MakeDeserialize(stream));
     427           0 :                 if (!tf.get()) {    // failed to deserialize
     428             :                     // fTFPlayback asserts it never has a null, so we plop in
     429             :                     // the default here.
     430           0 :                     tf = SkTypeface::MakeDefault();
     431             :                 }
     432           0 :                 fTFPlayback.set(i, tf.get());
     433             :             }
     434           0 :         } break;
     435             :         case SK_PICT_PICTURE_TAG: {
     436           0 :             fPictureCount = 0;
     437           0 :             fPictureRefs = new const SkPicture* [size];
     438           0 :             for (uint32_t i = 0; i < size; i++) {
     439           0 :                 fPictureRefs[i] = SkPicture::MakeFromStream(stream, factory, topLevelTFPlayback).release();
     440           0 :                 if (!fPictureRefs[i]) {
     441           0 :                     return false;
     442             :                 }
     443           0 :                 fPictureCount++;
     444             :             }
     445           0 :         } break;
     446             :         case SK_PICT_BUFFER_SIZE_TAG: {
     447           0 :             SkAutoMalloc storage(size);
     448           0 :             if (stream->read(storage.get(), size) != size) {
     449           0 :                 return false;
     450             :             }
     451             : 
     452             :             /* Should we use SkValidatingReadBuffer instead? */
     453           0 :             SkReadBuffer buffer(storage.get(), size);
     454           0 :             buffer.setFlags(pictInfoFlagsToReadBufferFlags(fInfo.fFlags));
     455           0 :             buffer.setVersion(fInfo.getVersion());
     456             : 
     457           0 :             if (!fFactoryPlayback) {
     458           0 :                 return false;
     459             :             }
     460           0 :             fFactoryPlayback->setupBuffer(buffer);
     461           0 :             buffer.setImageDeserializer(factory);
     462             : 
     463           0 :             if (fTFPlayback.count() > 0) {
     464             :                 // .skp files <= v43 have typefaces serialized with each sub picture.
     465           0 :                 fTFPlayback.setupBuffer(buffer);
     466             :             } else {
     467             :                 // Newer .skp files serialize all typefaces with the top picture.
     468           0 :                 topLevelTFPlayback->setupBuffer(buffer);
     469             :             }
     470             : 
     471           0 :             while (!buffer.eof() && buffer.isValid()) {
     472           0 :                 tag = buffer.readUInt();
     473           0 :                 size = buffer.readUInt();
     474           0 :                 if (!this->parseBufferTag(buffer, tag, size)) {
     475           0 :                     return false;
     476             :                 }
     477             :             }
     478           0 :             if (!buffer.isValid()) {
     479           0 :                 return false;
     480             :             }
     481           0 :             SkDEBUGCODE(haveBuffer = true;)
     482           0 :         } break;
     483             :     }
     484           0 :     return true;    // success
     485             : }
     486             : 
     487           0 : static const SkImage* create_image_from_buffer(SkReadBuffer& buffer) {
     488           0 :     return buffer.readImage().release();
     489             : }
     490           0 : static const SkVertices* create_vertices_from_buffer(SkReadBuffer& buffer) {
     491           0 :     auto data = buffer.readByteArrayAsData();
     492           0 :     return data ? SkVertices::Decode(data->data(), data->size()).release() : nullptr;
     493             : }
     494             : 
     495           0 : static const SkImage* create_bitmap_image_from_buffer(SkReadBuffer& buffer) {
     496           0 :     return buffer.readBitmapAsImage().release();
     497             : }
     498             : 
     499             : // Need a shallow wrapper to return const SkPicture* to match the other factories,
     500             : // as SkPicture::CreateFromBuffer() returns SkPicture*
     501           0 : static const SkPicture* create_picture_from_buffer(SkReadBuffer& buffer) {
     502           0 :     return SkPicture::MakeFromBuffer(buffer).release();
     503             : }
     504             : 
     505           0 : static const SkDrawable* create_drawable_from_buffer(SkReadBuffer& buffer) {
     506           0 :     return (SkDrawable*) buffer.readFlattenable(SkFlattenable::kSkDrawable_Type);
     507             : }
     508             : 
     509             : template <typename T>
     510           0 : bool new_array_from_buffer(SkReadBuffer& buffer, uint32_t inCount,
     511             :                            const T*** array, int* outCount, const T* (*factory)(SkReadBuffer&)) {
     512           0 :     if (!buffer.validate((0 == *outCount) && (nullptr == *array))) {
     513           0 :         return false;
     514             :     }
     515           0 :     if (0 == inCount) {
     516           0 :         return true;
     517             :     }
     518           0 :     if (!buffer.validate(SkTFitsIn<int>(inCount))) {
     519           0 :         return false;
     520             :     }
     521             : 
     522           0 :     *outCount = inCount;
     523           0 :     *array = new const T* [*outCount];
     524           0 :     bool success = true;
     525           0 :     int i = 0;
     526           0 :     for (; i < *outCount; i++) {
     527           0 :         (*array)[i] = factory(buffer);
     528           0 :         if (nullptr == (*array)[i]) {
     529           0 :             success = false;
     530           0 :             break;
     531             :         }
     532             :     }
     533           0 :     if (!success) {
     534             :         // Delete all of the blobs that were already created (up to but excluding i):
     535           0 :         for (int j = 0; j < i; j++) {
     536           0 :             (*array)[j]->unref();
     537             :         }
     538             :         // Delete the array
     539           0 :         delete[] * array;
     540           0 :         *array = nullptr;
     541           0 :         *outCount = 0;
     542           0 :         return false;
     543             :     }
     544           0 :     return true;
     545             : }
     546             : 
     547           0 : bool SkPictureData::parseBufferTag(SkReadBuffer& buffer, uint32_t tag, uint32_t size) {
     548           0 :     switch (tag) {
     549             :         case SK_PICT_BITMAP_BUFFER_TAG:
     550           0 :             if (!new_array_from_buffer(buffer, size, &fBitmapImageRefs, &fBitmapImageCount,
     551             :                                        create_bitmap_image_from_buffer)) {
     552           0 :                 return false;
     553             :             }
     554           0 :             break;
     555             :         case SK_PICT_PAINT_BUFFER_TAG: {
     556           0 :             if (!buffer.validate(SkTFitsIn<int>(size))) {
     557           0 :                 return false;
     558             :             }
     559           0 :             const int count = SkToInt(size);
     560           0 :             fPaints.reset(count);
     561           0 :             for (int i = 0; i < count; ++i) {
     562           0 :                 buffer.readPaint(&fPaints[i]);
     563             :             }
     564           0 :         } break;
     565             :         case SK_PICT_PATH_BUFFER_TAG:
     566           0 :             if (size > 0) {
     567           0 :                 const int count = buffer.readInt();
     568           0 :                 fPaths.reset(count);
     569           0 :                 for (int i = 0; i < count; i++) {
     570           0 :                     buffer.readPath(&fPaths[i]);
     571             :                 }
     572           0 :             } break;
     573             :         case SK_PICT_TEXTBLOB_BUFFER_TAG:
     574           0 :             if (!new_array_from_buffer(buffer, size, &fTextBlobRefs, &fTextBlobCount,
     575             :                                        SkTextBlob::CreateFromBuffer)) {
     576           0 :                 return false;
     577             :             }
     578           0 :             break;
     579             :         case SK_PICT_VERTICES_BUFFER_TAG:
     580           0 :             if (!new_array_from_buffer(buffer, size, &fVerticesRefs, &fVerticesCount,
     581             :                                        create_vertices_from_buffer)) {
     582           0 :                 return false;
     583             :             }
     584           0 :             break;
     585             :         case SK_PICT_IMAGE_BUFFER_TAG:
     586           0 :             if (!new_array_from_buffer(buffer, size, &fImageRefs, &fImageCount,
     587             :                                        create_image_from_buffer)) {
     588           0 :                 return false;
     589             :             }
     590           0 :             break;
     591             :         case SK_PICT_READER_TAG: {
     592           0 :             auto data(SkData::MakeUninitialized(size));
     593           0 :             if (!buffer.readByteArray(data->writable_data(), size) ||
     594           0 :                 !buffer.validate(nullptr == fOpData)) {
     595           0 :                 return false;
     596             :             }
     597           0 :             SkASSERT(nullptr == fOpData);
     598           0 :             fOpData = std::move(data);
     599           0 :         } break;
     600             :         case SK_PICT_PICTURE_TAG:
     601           0 :             if (!new_array_from_buffer(buffer, size, &fPictureRefs, &fPictureCount,
     602             :                                        create_picture_from_buffer)) {
     603           0 :                 return false;
     604             :             }
     605           0 :             break;
     606             :         case SK_PICT_DRAWABLE_TAG:
     607           0 :             if (!new_array_from_buffer(buffer, size, (const SkDrawable***)&fDrawableRefs,
     608             :                                        &fDrawableCount, create_drawable_from_buffer)) {
     609           0 :                 return false;
     610             :             }
     611           0 :             break;
     612             :         default:
     613             :             // The tag was invalid.
     614           0 :             return false;
     615             :     }
     616           0 :     return true;    // success
     617             : }
     618             : 
     619           0 : SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
     620             :                                                const SkPictInfo& info,
     621             :                                                SkImageDeserializer* factory,
     622             :                                                SkTypefacePlayback* topLevelTFPlayback) {
     623           0 :     std::unique_ptr<SkPictureData> data(new SkPictureData(info));
     624           0 :     if (!topLevelTFPlayback) {
     625           0 :         topLevelTFPlayback = &data->fTFPlayback;
     626             :     }
     627             : 
     628           0 :     if (!data->parseStream(stream, factory, topLevelTFPlayback)) {
     629           0 :         return nullptr;
     630             :     }
     631           0 :     return data.release();
     632             : }
     633             : 
     634           0 : SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer,
     635             :                                                const SkPictInfo& info) {
     636           0 :     std::unique_ptr<SkPictureData> data(new SkPictureData(info));
     637           0 :     buffer.setVersion(info.getVersion());
     638             : 
     639           0 :     if (!data->parseBuffer(buffer)) {
     640           0 :         return nullptr;
     641             :     }
     642           0 :     return data.release();
     643             : }
     644             : 
     645           0 : bool SkPictureData::parseStream(SkStream* stream,
     646             :                                 SkImageDeserializer* factory,
     647             :                                 SkTypefacePlayback* topLevelTFPlayback) {
     648             :     for (;;) {
     649           0 :         uint32_t tag = stream->readU32();
     650           0 :         if (SK_PICT_EOF_TAG == tag) {
     651           0 :             break;
     652             :         }
     653             : 
     654           0 :         uint32_t size = stream->readU32();
     655           0 :         if (!this->parseStreamTag(stream, tag, size, factory, topLevelTFPlayback)) {
     656           0 :             return false; // we're invalid
     657             :         }
     658           0 :     }
     659           0 :     return true;
     660             : }
     661             : 
     662           0 : bool SkPictureData::parseBuffer(SkReadBuffer& buffer) {
     663             :     for (;;) {
     664           0 :         uint32_t tag = buffer.readUInt();
     665           0 :         if (SK_PICT_EOF_TAG == tag) {
     666           0 :             break;
     667             :         }
     668             : 
     669           0 :         uint32_t size = buffer.readUInt();
     670           0 :         if (!this->parseBufferTag(buffer, tag, size)) {
     671           0 :             return false; // we're invalid
     672             :         }
     673           0 :     }
     674           0 :     return true;
     675             : }
     676             : 
     677             : ///////////////////////////////////////////////////////////////////////////////
     678             : ///////////////////////////////////////////////////////////////////////////////
     679             : 
     680             : #if SK_SUPPORT_GPU
     681           0 : bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
     682             :                                                 int sampleCount) const {
     683           0 :     return fContentInfo.suitableForGpuRasterization(context, reason, sampleCount);
     684             : }
     685             : 
     686           0 : bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
     687             :                                                 GrPixelConfig config, SkScalar dpi) const {
     688             : 
     689           0 :     if (context != nullptr) {
     690           0 :         return this->suitableForGpuRasterization(context, reason,
     691           0 :                                                  context->getRecommendedSampleCount(config, dpi));
     692             :     } else {
     693           0 :         return this->suitableForGpuRasterization(nullptr, reason);
     694             :     }
     695             : }
     696             : 
     697           0 : bool SkPictureData::suitableForLayerOptimization() const {
     698           0 :     return fContentInfo.numLayers() > 0;
     699             : }
     700             : #endif
     701             : ///////////////////////////////////////////////////////////////////////////////

Generated by: LCOV version 1.13