Home | History | Annotate | Download | only in core
      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 #include <new>
      8 #include "SkBBoxHierarchy.h"
      9 #include "SkDrawPictureCallback.h"
     10 #include "SkPictureData.h"
     11 #include "SkPictureRecord.h"
     12 #include "SkReadBuffer.h"
     13 #include "SkTextBlob.h"
     14 #include "SkTypeface.h"
     15 #include "SkTSort.h"
     16 #include "SkWriteBuffer.h"
     17 
     18 #if SK_SUPPORT_GPU
     19 #include "GrContext.h"
     20 #endif
     21 
     22 template <typename T> int SafeCount(const T* obj) {
     23     return obj ? obj->count() : 0;
     24 }
     25 
     26 SkPictureData::SkPictureData(const SkPictInfo& info)
     27     : fInfo(info) {
     28     this->init();
     29 }
     30 
     31 void SkPictureData::initForPlayback() const {
     32     // ensure that the paths bounds are pre-computed
     33     if (fPathHeap.get()) {
     34         for (int i = 0; i < fPathHeap->count(); i++) {
     35             (*fPathHeap.get())[i].updateBoundsCache();
     36         }
     37     }
     38 }
     39 
     40 SkPictureData::SkPictureData(const SkPictureRecord& record,
     41                              const SkPictInfo& info,
     42                              bool deepCopyOps)
     43     : fInfo(info) {
     44 
     45     this->init();
     46 
     47     fOpData = record.opData(deepCopyOps);
     48 
     49     fBoundingHierarchy = record.fBoundingHierarchy;
     50     fStateTree = record.fStateTree;
     51 
     52     SkSafeRef(fBoundingHierarchy);
     53     SkSafeRef(fStateTree);
     54     fContentInfo.set(record.fContentInfo);
     55 
     56     if (fBoundingHierarchy) {
     57         fBoundingHierarchy->flushDeferredInserts();
     58     }
     59 
     60     // copy over the refcnt dictionary to our reader
     61     record.fFlattenableHeap.setupPlaybacks();
     62 
     63     fBitmaps = record.fBitmapHeap->extractBitmaps();
     64     fPaints = record.fPaints.unflattenToArray();
     65 
     66     fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap));
     67     fPathHeap.reset(SkSafeRef(record.pathHeap()));
     68 
     69     this->initForPlayback();
     70 
     71     const SkTDArray<const SkPicture* >& pictures = record.getPictureRefs();
     72     fPictureCount = pictures.count();
     73     if (fPictureCount > 0) {
     74         fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
     75         for (int i = 0; i < fPictureCount; i++) {
     76             fPictureRefs[i] = pictures[i];
     77             fPictureRefs[i]->ref();
     78         }
     79     }
     80 
     81     // templatize to consolidate with similar picture logic?
     82     const SkTDArray<const SkTextBlob*>& blobs = record.getTextBlobRefs();
     83     fTextBlobCount = blobs.count();
     84     if (fTextBlobCount > 0) {
     85         fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount);
     86         for (int i = 0; i < fTextBlobCount; ++i) {
     87             fTextBlobRefs[i] = SkRef(blobs[i]);
     88         }
     89     }
     90 }
     91 
     92 #ifdef SK_SUPPORT_LEGACY_PICTURE_CLONE
     93 SkPictureData::SkPictureData(const SkPictureData& src, SkPictCopyInfo* deepCopyInfo)
     94     : fInfo(src.fInfo) {
     95     this->init();
     96 
     97     fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get()));
     98     fPathHeap.reset(SkSafeRef(src.fPathHeap.get()));
     99 
    100     fOpData = SkSafeRef(src.fOpData);
    101 
    102     fBoundingHierarchy = src.fBoundingHierarchy;
    103     fStateTree = src.fStateTree;
    104     fContentInfo.set(src.fContentInfo);
    105 
    106     SkSafeRef(fBoundingHierarchy);
    107     SkSafeRef(fStateTree);
    108 
    109     if (deepCopyInfo) {
    110         int paintCount = SafeCount(src.fPaints);
    111 
    112         if (src.fBitmaps) {
    113             fBitmaps = SkTRefArray<SkBitmap>::Create(src.fBitmaps->begin(), src.fBitmaps->count());
    114         }
    115 
    116         fPaints = SkTRefArray<SkPaint>::Create(paintCount);
    117         SkASSERT(deepCopyInfo->paintData.count() == paintCount);
    118         SkBitmapHeap* bmHeap = deepCopyInfo->controller.getBitmapHeap();
    119         SkTypefacePlayback* tfPlayback = deepCopyInfo->controller.getTypefacePlayback();
    120         for (int i = 0; i < paintCount; i++) {
    121             if (deepCopyInfo->paintData[i]) {
    122                 deepCopyInfo->paintData[i]->unflatten<SkPaint::FlatteningTraits>(
    123                     &fPaints->writableAt(i), bmHeap, tfPlayback);
    124             } else {
    125                 // needs_deep_copy was false, so just need to assign
    126                 fPaints->writableAt(i) = src.fPaints->at(i);
    127             }
    128         }
    129 
    130     } else {
    131         fBitmaps = SkSafeRef(src.fBitmaps);
    132         fPaints = SkSafeRef(src.fPaints);
    133     }
    134 
    135     fPictureCount = src.fPictureCount;
    136     fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
    137     for (int i = 0; i < fPictureCount; i++) {
    138         if (deepCopyInfo) {
    139             fPictureRefs[i] = src.fPictureRefs[i]->clone();
    140         } else {
    141             fPictureRefs[i] = src.fPictureRefs[i];
    142             fPictureRefs[i]->ref();
    143         }
    144     }
    145 }
    146 #endif//SK_SUPPORT_LEGACY_PICTURE_CLONE
    147 
    148 void SkPictureData::init() {
    149     fBitmaps = NULL;
    150     fPaints = NULL;
    151     fPictureRefs = NULL;
    152     fPictureCount = 0;
    153     fTextBlobRefs = NULL;
    154     fTextBlobCount = 0;
    155     fOpData = NULL;
    156     fFactoryPlayback = NULL;
    157     fBoundingHierarchy = NULL;
    158     fStateTree = NULL;
    159 }
    160 
    161 SkPictureData::~SkPictureData() {
    162     SkSafeUnref(fOpData);
    163 
    164     SkSafeUnref(fBitmaps);
    165     SkSafeUnref(fPaints);
    166     SkSafeUnref(fBoundingHierarchy);
    167     SkSafeUnref(fStateTree);
    168 
    169     for (int i = 0; i < fPictureCount; i++) {
    170         fPictureRefs[i]->unref();
    171     }
    172     SkDELETE_ARRAY(fPictureRefs);
    173 
    174     for (int i = 0; i < fTextBlobCount; i++) {
    175         fTextBlobRefs[i]->unref();
    176     }
    177     SkDELETE_ARRAY(fTextBlobRefs);
    178 
    179     SkDELETE(fFactoryPlayback);
    180 }
    181 
    182 bool SkPictureData::containsBitmaps() const {
    183     if (fBitmaps && fBitmaps->count() > 0) {
    184         return true;
    185     }
    186     for (int i = 0; i < fPictureCount; ++i) {
    187         if (fPictureRefs[i]->willPlayBackBitmaps()) {
    188             return true;
    189         }
    190     }
    191     return false;
    192 }
    193 
    194 ///////////////////////////////////////////////////////////////////////////////
    195 ///////////////////////////////////////////////////////////////////////////////
    196 
    197 #include "SkStream.h"
    198 
    199 static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
    200     size_t size = 4;  // for 'count'
    201 
    202     for (int i = 0; i < count; i++) {
    203         const char* name = SkFlattenable::FactoryToName(array[i]);
    204         if (NULL == name || 0 == *name) {
    205             size += SkWStream::SizeOfPackedUInt(0);
    206         } else {
    207             size_t len = strlen(name);
    208             size += SkWStream::SizeOfPackedUInt(len);
    209             size += len;
    210         }
    211     }
    212 
    213     return size;
    214 }
    215 
    216 static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, size_t size) {
    217     buffer.writeUInt(tag);
    218     buffer.writeUInt(SkToU32(size));
    219 }
    220 
    221 static void write_tag_size(SkWStream* stream, uint32_t tag, size_t size) {
    222     stream->write32(tag);
    223     stream->write32(SkToU32(size));
    224 }
    225 
    226 void SkPictureData::WriteFactories(SkWStream* stream, const SkFactorySet& rec) {
    227     int count = rec.count();
    228 
    229     SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
    230     SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
    231     rec.copyToArray(array);
    232 
    233     size_t size = compute_chunk_size(array, count);
    234 
    235     // TODO: write_tag_size should really take a size_t
    236     write_tag_size(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
    237     SkDEBUGCODE(size_t start = stream->bytesWritten());
    238     stream->write32(count);
    239 
    240     for (int i = 0; i < count; i++) {
    241         const char* name = SkFlattenable::FactoryToName(array[i]);
    242         if (NULL == name || 0 == *name) {
    243             stream->writePackedUInt(0);
    244         } else {
    245             size_t len = strlen(name);
    246             stream->writePackedUInt(len);
    247             stream->write(name, len);
    248         }
    249     }
    250 
    251     SkASSERT(size == (stream->bytesWritten() - start));
    252 }
    253 
    254 void SkPictureData::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
    255     int count = rec.count();
    256 
    257     write_tag_size(stream, SK_PICT_TYPEFACE_TAG, count);
    258 
    259     SkAutoSTMalloc<16, SkTypeface*> storage(count);
    260     SkTypeface** array = (SkTypeface**)storage.get();
    261     rec.copyToArray((SkRefCnt**)array);
    262 
    263     for (int i = 0; i < count; i++) {
    264         array[i]->serialize(stream);
    265     }
    266 }
    267 
    268 void SkPictureData::flattenToBuffer(SkWriteBuffer& buffer) const {
    269     int i, n;
    270 
    271     if ((n = SafeCount(fBitmaps)) > 0) {
    272         write_tag_size(buffer, SK_PICT_BITMAP_BUFFER_TAG, n);
    273         for (i = 0; i < n; i++) {
    274             buffer.writeBitmap((*fBitmaps)[i]);
    275         }
    276     }
    277 
    278     if ((n = SafeCount(fPaints)) > 0) {
    279         write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
    280         for (i = 0; i < n; i++) {
    281             buffer.writePaint((*fPaints)[i]);
    282         }
    283     }
    284 
    285     if ((n = SafeCount(fPathHeap.get())) > 0) {
    286         write_tag_size(buffer, SK_PICT_PATH_BUFFER_TAG, n);
    287         fPathHeap->flatten(buffer);
    288     }
    289 
    290     if (fTextBlobCount > 0) {
    291         write_tag_size(buffer, SK_PICT_TEXTBLOB_BUFFER_TAG, fTextBlobCount);
    292         for (i = 0; i  < fTextBlobCount; ++i) {
    293             fTextBlobRefs[i]->flatten(buffer);
    294         }
    295     }
    296 }
    297 
    298 void SkPictureData::serialize(SkWStream* stream,
    299                                   SkPicture::EncodeBitmap encoder) const {
    300     write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size());
    301     stream->write(fOpData->bytes(), fOpData->size());
    302 
    303     if (fPictureCount > 0) {
    304         write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
    305         for (int i = 0; i < fPictureCount; i++) {
    306             fPictureRefs[i]->serialize(stream, encoder);
    307         }
    308     }
    309 
    310     // Write some of our data into a writebuffer, and then serialize that
    311     // into our stream
    312     {
    313         SkRefCntSet  typefaceSet;
    314         SkFactorySet factSet;
    315 
    316         SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag);
    317         buffer.setTypefaceRecorder(&typefaceSet);
    318         buffer.setFactoryRecorder(&factSet);
    319         buffer.setBitmapEncoder(encoder);
    320 
    321         this->flattenToBuffer(buffer);
    322 
    323         // We have to write these two sets into the stream *before* we write
    324         // the buffer, since parsing that buffer will require that we already
    325         // have these sets available to use.
    326         WriteFactories(stream, factSet);
    327         WriteTypefaces(stream, typefaceSet);
    328 
    329         write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
    330         buffer.writeToStream(stream);
    331     }
    332 
    333     stream->write32(SK_PICT_EOF_TAG);
    334 }
    335 
    336 void SkPictureData::flatten(SkWriteBuffer& buffer) const {
    337     write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size());
    338     buffer.writeByteArray(fOpData->bytes(), fOpData->size());
    339 
    340     if (fPictureCount > 0) {
    341         write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictureCount);
    342         for (int i = 0; i < fPictureCount; i++) {
    343             fPictureRefs[i]->flatten(buffer);
    344         }
    345     }
    346 
    347     // Write this picture playback's data into a writebuffer
    348     this->flattenToBuffer(buffer);
    349     buffer.write32(SK_PICT_EOF_TAG);
    350 }
    351 
    352 ///////////////////////////////////////////////////////////////////////////////
    353 
    354 /**
    355  *  Return the corresponding SkReadBuffer flags, given a set of
    356  *  SkPictInfo flags.
    357  */
    358 static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
    359     static const struct {
    360         uint32_t    fSrc;
    361         uint32_t    fDst;
    362     } gSD[] = {
    363         { SkPictInfo::kCrossProcess_Flag,   SkReadBuffer::kCrossProcess_Flag },
    364         { SkPictInfo::kScalarIsFloat_Flag,  SkReadBuffer::kScalarIsFloat_Flag },
    365         { SkPictInfo::kPtrIs64Bit_Flag,     SkReadBuffer::kPtrIs64Bit_Flag },
    366     };
    367 
    368     uint32_t rbMask = 0;
    369     for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) {
    370         if (pictInfoFlags & gSD[i].fSrc) {
    371             rbMask |= gSD[i].fDst;
    372         }
    373     }
    374     return rbMask;
    375 }
    376 
    377 bool SkPictureData::parseStreamTag(SkStream* stream,
    378                                    uint32_t tag,
    379                                    uint32_t size,
    380                                    SkPicture::InstallPixelRefProc proc) {
    381     /*
    382      *  By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
    383      *  its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
    384      *  but if they are present, they need to have been seen before the buffer.
    385      *
    386      *  We assert that if/when we see either of these, that we have not yet seen
    387      *  the buffer tag, because if we have, then its too-late to deal with the
    388      *  factories or typefaces.
    389      */
    390     SkDEBUGCODE(bool haveBuffer = false;)
    391 
    392     switch (tag) {
    393         case SK_PICT_READER_TAG:
    394             SkASSERT(NULL == fOpData);
    395             fOpData = SkData::NewFromStream(stream, size);
    396             if (!fOpData) {
    397                 return false;
    398             }
    399             break;
    400         case SK_PICT_FACTORY_TAG: {
    401             SkASSERT(!haveBuffer);
    402         // Remove this code when v21 and below are no longer supported. At the
    403         // same time add a new 'count' variable and use it rather then reusing 'size'.
    404 #ifndef DISABLE_V21_COMPATIBILITY_CODE
    405             if (fInfo.fVersion >= 22) {
    406                 // in v22 this tag's size represents the size of the chunk in bytes
    407                 // and the number of factory strings is written out separately
    408 #endif
    409                 size = stream->readU32();
    410 #ifndef DISABLE_V21_COMPATIBILITY_CODE
    411             }
    412 #endif
    413             fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size));
    414             for (size_t i = 0; i < size; i++) {
    415                 SkString str;
    416                 const size_t len = stream->readPackedUInt();
    417                 str.resize(len);
    418                 if (stream->read(str.writable_str(), len) != len) {
    419                     return false;
    420                 }
    421                 fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
    422             }
    423         } break;
    424         case SK_PICT_TYPEFACE_TAG: {
    425             SkASSERT(!haveBuffer);
    426             const int count = SkToInt(size);
    427             fTFPlayback.setCount(count);
    428             for (int i = 0; i < count; i++) {
    429                 SkAutoTUnref<SkTypeface> tf(SkTypeface::Deserialize(stream));
    430                 if (!tf.get()) {    // failed to deserialize
    431                     // fTFPlayback asserts it never has a null, so we plop in
    432                     // the default here.
    433                     tf.reset(SkTypeface::RefDefault());
    434                 }
    435                 fTFPlayback.set(i, tf);
    436             }
    437         } break;
    438         case SK_PICT_PICTURE_TAG: {
    439             fPictureCount = size;
    440             fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
    441             bool success = true;
    442             int i = 0;
    443             for ( ; i < fPictureCount; i++) {
    444                 fPictureRefs[i] = SkPicture::CreateFromStream(stream, proc);
    445                 if (NULL == fPictureRefs[i]) {
    446                     success = false;
    447                     break;
    448                 }
    449             }
    450             if (!success) {
    451                 // Delete all of the pictures that were already created (up to but excluding i):
    452                 for (int j = 0; j < i; j++) {
    453                     fPictureRefs[j]->unref();
    454                 }
    455                 // Delete the array
    456                 SkDELETE_ARRAY(fPictureRefs);
    457                 fPictureCount = 0;
    458                 return false;
    459             }
    460         } break;
    461         case SK_PICT_BUFFER_SIZE_TAG: {
    462             SkAutoMalloc storage(size);
    463             if (stream->read(storage.get(), size) != size) {
    464                 return false;
    465             }
    466 
    467             SkReadBuffer buffer(storage.get(), size);
    468             buffer.setFlags(pictInfoFlagsToReadBufferFlags(fInfo.fFlags));
    469             buffer.setVersion(fInfo.fVersion);
    470 
    471             fFactoryPlayback->setupBuffer(buffer);
    472             fTFPlayback.setupBuffer(buffer);
    473             buffer.setBitmapDecoder(proc);
    474 
    475             while (!buffer.eof()) {
    476                 tag = buffer.readUInt();
    477                 size = buffer.readUInt();
    478                 if (!this->parseBufferTag(buffer, tag, size)) {
    479                     return false;
    480                 }
    481             }
    482             SkDEBUGCODE(haveBuffer = true;)
    483         } break;
    484     }
    485     return true;    // success
    486 }
    487 
    488 bool SkPictureData::parseBufferTag(SkReadBuffer& buffer,
    489                                    uint32_t tag, uint32_t size) {
    490     switch (tag) {
    491         case SK_PICT_BITMAP_BUFFER_TAG: {
    492             const int count = SkToInt(size);
    493             fBitmaps = SkTRefArray<SkBitmap>::Create(size);
    494             for (int i = 0; i < count; ++i) {
    495                 SkBitmap* bm = &fBitmaps->writableAt(i);
    496                 buffer.readBitmap(bm);
    497                 bm->setImmutable();
    498             }
    499         } break;
    500         case SK_PICT_PAINT_BUFFER_TAG: {
    501             const int count = SkToInt(size);
    502             fPaints = SkTRefArray<SkPaint>::Create(size);
    503             for (int i = 0; i < count; ++i) {
    504                 buffer.readPaint(&fPaints->writableAt(i));
    505             }
    506         } break;
    507         case SK_PICT_PATH_BUFFER_TAG:
    508             if (size > 0) {
    509                 fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer)));
    510             }
    511             break;
    512         case SK_PICT_TEXTBLOB_BUFFER_TAG: {
    513             if (!buffer.validate((0 == fTextBlobCount) && (NULL == fTextBlobRefs))) {
    514                 return false;
    515             }
    516             fTextBlobCount = size;
    517             fTextBlobRefs = SkNEW_ARRAY(const SkTextBlob*, fTextBlobCount);
    518             bool success = true;
    519             int i = 0;
    520             for ( ; i < fTextBlobCount; i++) {
    521                 fTextBlobRefs[i] = SkTextBlob::CreateFromBuffer(buffer);
    522                 if (NULL == fTextBlobRefs[i]) {
    523                     success = false;
    524                     break;
    525                 }
    526             }
    527             if (!success) {
    528                 // Delete all of the blobs that were already created (up to but excluding i):
    529                 for (int j = 0; j < i; j++) {
    530                     fTextBlobRefs[j]->unref();
    531                 }
    532                 // Delete the array
    533                 SkDELETE_ARRAY(fTextBlobRefs);
    534                 fTextBlobRefs = NULL;
    535                 fTextBlobCount = 0;
    536                 return false;
    537             }
    538         } break;
    539         case SK_PICT_READER_TAG: {
    540             SkAutoDataUnref data(SkData::NewUninitialized(size));
    541             if (!buffer.readByteArray(data->writable_data(), size) ||
    542                 !buffer.validate(NULL == fOpData)) {
    543                 return false;
    544             }
    545             SkASSERT(NULL == fOpData);
    546             fOpData = data.detach();
    547         } break;
    548         case SK_PICT_PICTURE_TAG: {
    549             if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs))) {
    550                 return false;
    551             }
    552             fPictureCount = size;
    553             fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
    554             bool success = true;
    555             int i = 0;
    556             for ( ; i < fPictureCount; i++) {
    557                 fPictureRefs[i] = SkPicture::CreateFromBuffer(buffer);
    558                 if (NULL == fPictureRefs[i]) {
    559                     success = false;
    560                     break;
    561                 }
    562             }
    563             if (!success) {
    564                 // Delete all of the pictures that were already created (up to but excluding i):
    565                 for (int j = 0; j < i; j++) {
    566                     fPictureRefs[j]->unref();
    567                 }
    568                 // Delete the array
    569                 SkDELETE_ARRAY(fPictureRefs);
    570                 fPictureCount = 0;
    571                 return false;
    572             }
    573         } break;
    574         default:
    575             // The tag was invalid.
    576             return false;
    577     }
    578     return true;    // success
    579 }
    580 
    581 SkPictureData* SkPictureData::CreateFromStream(SkStream* stream,
    582                                                const SkPictInfo& info,
    583                                                SkPicture::InstallPixelRefProc proc) {
    584     SkAutoTDelete<SkPictureData> data(SkNEW_ARGS(SkPictureData, (info)));
    585 
    586     if (!data->parseStream(stream, proc)) {
    587         return NULL;
    588     }
    589     return data.detach();
    590 }
    591 
    592 SkPictureData* SkPictureData::CreateFromBuffer(SkReadBuffer& buffer,
    593                                                const SkPictInfo& info) {
    594     SkAutoTDelete<SkPictureData> data(SkNEW_ARGS(SkPictureData, (info)));
    595     buffer.setVersion(info.fVersion);
    596 
    597     if (!data->parseBuffer(buffer)) {
    598         return NULL;
    599     }
    600     return data.detach();
    601 }
    602 
    603 bool SkPictureData::parseStream(SkStream* stream,
    604                                 SkPicture::InstallPixelRefProc proc) {
    605     for (;;) {
    606         uint32_t tag = stream->readU32();
    607         if (SK_PICT_EOF_TAG == tag) {
    608             break;
    609         }
    610 
    611         uint32_t size = stream->readU32();
    612         if (!this->parseStreamTag(stream, tag, size, proc)) {
    613             return false; // we're invalid
    614         }
    615     }
    616     return true;
    617 }
    618 
    619 bool SkPictureData::parseBuffer(SkReadBuffer& buffer) {
    620     for (;;) {
    621         uint32_t tag = buffer.readUInt();
    622         if (SK_PICT_EOF_TAG == tag) {
    623             break;
    624         }
    625 
    626         uint32_t size = buffer.readUInt();
    627         if (!this->parseBufferTag(buffer, tag, size)) {
    628             return false; // we're invalid
    629         }
    630     }
    631     return true;
    632 }
    633 
    634 ///////////////////////////////////////////////////////////////////////////////
    635 ///////////////////////////////////////////////////////////////////////////////
    636 
    637 const SkPicture::OperationList* SkPictureData::getActiveOps(const SkRect& query) const {
    638     if (NULL == fStateTree || NULL == fBoundingHierarchy) {
    639         return NULL;
    640     }
    641 
    642     SkPicture::OperationList* activeOps = SkNEW(SkPicture::OperationList);
    643     fBoundingHierarchy->search(query, &(activeOps->fOps));
    644     return activeOps;
    645 }
    646 
    647 #if SK_SUPPORT_GPU
    648 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
    649                                                 int sampleCount) const {
    650     return fContentInfo.suitableForGpuRasterization(context, reason, sampleCount);
    651 }
    652 
    653 bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
    654                                                 GrPixelConfig config, SkScalar dpi) const {
    655 
    656     if (context != NULL) {
    657         return this->suitableForGpuRasterization(context, reason,
    658                                                  context->getRecommendedSampleCount(config, dpi));
    659     } else {
    660         return this->suitableForGpuRasterization(NULL, reason);
    661     }
    662 }
    663 
    664 bool SkPictureData::suitableForLayerOptimization() const {
    665     return fContentInfo.numLayers() > 0;
    666 }
    667 #endif
    668 ///////////////////////////////////////////////////////////////////////////////
    669 
    670 
    671