Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2012 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "SkOrderedWriteBuffer.h"
     10 #include "SkBitmap.h"
     11 #include "SkData.h"
     12 #include "SkPixelRef.h"
     13 #include "SkPtrRecorder.h"
     14 #include "SkStream.h"
     15 #include "SkTypeface.h"
     16 
     17 SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize)
     18     : INHERITED()
     19     , fFactorySet(NULL)
     20     , fNamedFactorySet(NULL)
     21     , fWriter(minSize)
     22     , fBitmapHeap(NULL)
     23     , fTFSet(NULL)
     24     , fBitmapEncoder(NULL) {
     25 }
     26 
     27 SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize, void* storage, size_t storageSize)
     28     : INHERITED()
     29     , fFactorySet(NULL)
     30     , fNamedFactorySet(NULL)
     31     , fWriter(minSize, storage, storageSize)
     32     , fBitmapHeap(NULL)
     33     , fTFSet(NULL)
     34     , fBitmapEncoder(NULL) {
     35 }
     36 
     37 SkOrderedWriteBuffer::~SkOrderedWriteBuffer() {
     38     SkSafeUnref(fFactorySet);
     39     SkSafeUnref(fNamedFactorySet);
     40     SkSafeUnref(fBitmapHeap);
     41     SkSafeUnref(fTFSet);
     42 }
     43 
     44 void SkOrderedWriteBuffer::writeByteArray(const void* data, size_t size) {
     45     fWriter.write32(size);
     46     fWriter.writePad(data, size);
     47 }
     48 
     49 void SkOrderedWriteBuffer::writeBool(bool value) {
     50     fWriter.writeBool(value);
     51 }
     52 
     53 void SkOrderedWriteBuffer::writeFixed(SkFixed value) {
     54     fWriter.write32(value);
     55 }
     56 
     57 void SkOrderedWriteBuffer::writeScalar(SkScalar value) {
     58     fWriter.writeScalar(value);
     59 }
     60 
     61 void SkOrderedWriteBuffer::writeScalarArray(const SkScalar* value, uint32_t count) {
     62     fWriter.write32(count);
     63     fWriter.write(value, count * sizeof(SkScalar));
     64 }
     65 
     66 void SkOrderedWriteBuffer::writeInt(int32_t value) {
     67     fWriter.write32(value);
     68 }
     69 
     70 void SkOrderedWriteBuffer::writeIntArray(const int32_t* value, uint32_t count) {
     71     fWriter.write32(count);
     72     fWriter.write(value, count * sizeof(int32_t));
     73 }
     74 
     75 void SkOrderedWriteBuffer::writeUInt(uint32_t value) {
     76     fWriter.write32(value);
     77 }
     78 
     79 void SkOrderedWriteBuffer::write32(int32_t value) {
     80     fWriter.write32(value);
     81 }
     82 
     83 void SkOrderedWriteBuffer::writeString(const char* value) {
     84     fWriter.writeString(value);
     85 }
     86 
     87 void SkOrderedWriteBuffer::writeEncodedString(const void* value, size_t byteLength,
     88                                               SkPaint::TextEncoding encoding) {
     89     fWriter.writeInt(encoding);
     90     fWriter.writeInt(byteLength);
     91     fWriter.write(value, byteLength);
     92 }
     93 
     94 
     95 void SkOrderedWriteBuffer::writeColor(const SkColor& color) {
     96     fWriter.write32(color);
     97 }
     98 
     99 void SkOrderedWriteBuffer::writeColorArray(const SkColor* color, uint32_t count) {
    100     fWriter.write32(count);
    101     fWriter.write(color, count * sizeof(SkColor));
    102 }
    103 
    104 void SkOrderedWriteBuffer::writePoint(const SkPoint& point) {
    105     fWriter.writeScalar(point.fX);
    106     fWriter.writeScalar(point.fY);
    107 }
    108 
    109 void SkOrderedWriteBuffer::writePointArray(const SkPoint* point, uint32_t count) {
    110     fWriter.write32(count);
    111     fWriter.write(point, count * sizeof(SkPoint));
    112 }
    113 
    114 void SkOrderedWriteBuffer::writeMatrix(const SkMatrix& matrix) {
    115     fWriter.writeMatrix(matrix);
    116 }
    117 
    118 void SkOrderedWriteBuffer::writeIRect(const SkIRect& rect) {
    119     fWriter.write(&rect, sizeof(SkIRect));
    120 }
    121 
    122 void SkOrderedWriteBuffer::writeRect(const SkRect& rect) {
    123     fWriter.writeRect(rect);
    124 }
    125 
    126 void SkOrderedWriteBuffer::writeRegion(const SkRegion& region) {
    127     fWriter.writeRegion(region);
    128 }
    129 
    130 void SkOrderedWriteBuffer::writePath(const SkPath& path) {
    131     fWriter.writePath(path);
    132 }
    133 
    134 size_t SkOrderedWriteBuffer::writeStream(SkStream* stream, size_t length) {
    135     fWriter.write32(length);
    136     size_t bytesWritten = fWriter.readFromStream(stream, length);
    137     if (bytesWritten < length) {
    138         fWriter.reservePad(length - bytesWritten);
    139     }
    140     return bytesWritten;
    141 }
    142 
    143 bool SkOrderedWriteBuffer::writeToStream(SkWStream* stream) {
    144     return fWriter.writeToStream(stream);
    145 }
    146 
    147 void SkOrderedWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
    148     // Record information about the bitmap in one of three ways, in order of priority:
    149     // 1. If there is an SkBitmapHeap, store it in the heap. The client can avoid serializing the
    150     //    bitmap entirely or serialize it later as desired.
    151     // 2. Write an encoded version of the bitmap. Afterwards the width and height are written, so
    152     //    a reader without a decoder can draw a dummy bitmap of the right size.
    153     //    A. If the bitmap has an encoded representation, write it to the stream.
    154     //    B. If there is a function for encoding bitmaps, use it.
    155     // 3. Call SkBitmap::flatten.
    156     // For an encoded bitmap, write the size first. Otherwise store a 0 so the reader knows not to
    157     // decode.
    158     if (fBitmapHeap != NULL) {
    159         SkASSERT(NULL == fBitmapEncoder);
    160         // Bitmap was not encoded. Record a zero, implying that the reader need not decode.
    161         this->writeUInt(0);
    162         int32_t slot = fBitmapHeap->insert(bitmap);
    163         fWriter.write32(slot);
    164         // crbug.com/155875
    165         // The generation ID is not required information. We write it to prevent collisions
    166         // in SkFlatDictionary.  It is possible to get a collision when a previously
    167         // unflattened (i.e. stale) instance of a similar flattenable is in the dictionary
    168         // and the instance currently being written is re-using the same slot from the
    169         // bitmap heap.
    170         fWriter.write32(bitmap.getGenerationID());
    171         return;
    172     }
    173     bool encoded = false;
    174     // Before attempting to encode the SkBitmap, check to see if there is already an encoded
    175     // version.
    176     SkPixelRef* ref = bitmap.pixelRef();
    177     if (ref != NULL) {
    178         SkAutoDataUnref data(ref->refEncodedData());
    179         if (data.get() != NULL) {
    180             // Write the length to indicate that the bitmap was encoded successfully, followed
    181             // by the actual data. This must match the case where fBitmapEncoder is used so the
    182             // reader need not know the difference.
    183             this->writeUInt(data->size());
    184             fWriter.writePad(data->data(), data->size());
    185             encoded = true;
    186         }
    187     }
    188     if (fBitmapEncoder != NULL && !encoded) {
    189         SkASSERT(NULL == fBitmapHeap);
    190         SkDynamicMemoryWStream stream;
    191         if (fBitmapEncoder(&stream, bitmap)) {
    192             uint32_t offset = fWriter.bytesWritten();
    193             // Write the length to indicate that the bitmap was encoded successfully, followed
    194             // by the actual data. This must match the case where the original data is used so the
    195             // reader need not know the difference.
    196             size_t length = stream.getOffset();
    197             this->writeUInt(length);
    198             if (stream.read(fWriter.reservePad(length), 0, length)) {
    199                 encoded = true;
    200             } else {
    201                 // Writing the stream failed, so go back to original state to store another way.
    202                 fWriter.rewindToOffset(offset);
    203             }
    204         }
    205     }
    206     if (encoded) {
    207         // Write the width and height in case the reader does not have a decoder.
    208         this->writeInt(bitmap.width());
    209         this->writeInt(bitmap.height());
    210     } else {
    211         // Bitmap was not encoded. Record a zero, implying that the reader need not decode.
    212         this->writeUInt(0);
    213         bitmap.flatten(*this);
    214     }
    215 }
    216 
    217 void SkOrderedWriteBuffer::writeTypeface(SkTypeface* obj) {
    218     if (NULL == obj || NULL == fTFSet) {
    219         fWriter.write32(0);
    220     } else {
    221         fWriter.write32(fTFSet->add(obj));
    222     }
    223 }
    224 
    225 SkFactorySet* SkOrderedWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
    226     SkRefCnt_SafeAssign(fFactorySet, rec);
    227     if (fNamedFactorySet != NULL) {
    228         fNamedFactorySet->unref();
    229         fNamedFactorySet = NULL;
    230     }
    231     return rec;
    232 }
    233 
    234 SkNamedFactorySet* SkOrderedWriteBuffer::setNamedFactoryRecorder(SkNamedFactorySet* rec) {
    235     SkRefCnt_SafeAssign(fNamedFactorySet, rec);
    236     if (fFactorySet != NULL) {
    237         fFactorySet->unref();
    238         fFactorySet = NULL;
    239     }
    240     return rec;
    241 }
    242 
    243 SkRefCntSet* SkOrderedWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
    244     SkRefCnt_SafeAssign(fTFSet, rec);
    245     return rec;
    246 }
    247 
    248 void SkOrderedWriteBuffer::setBitmapHeap(SkBitmapHeap* bitmapHeap) {
    249     SkRefCnt_SafeAssign(fBitmapHeap, bitmapHeap);
    250     if (bitmapHeap != NULL) {
    251         SkASSERT(NULL == fBitmapEncoder);
    252         fBitmapEncoder = NULL;
    253     }
    254 }
    255 
    256 void SkOrderedWriteBuffer::setBitmapEncoder(SkSerializationHelpers::EncodeBitmap bitmapEncoder) {
    257     fBitmapEncoder = bitmapEncoder;
    258     if (bitmapEncoder != NULL) {
    259         SkASSERT(NULL == fBitmapHeap);
    260         SkSafeUnref(fBitmapHeap);
    261         fBitmapHeap = NULL;
    262     }
    263 }
    264 
    265 void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
    266     /*
    267      *  If we have a factoryset, then the first 32bits tell us...
    268      *       0: failure to write the flattenable
    269      *      >0: (1-based) index into the SkFactorySet or SkNamedFactorySet
    270      *  If we don't have a factoryset, then the first "ptr" is either the
    271      *  factory, or null for failure.
    272      *
    273      *  The distinction is important, since 0-index is 32bits (always), but a
    274      *  0-functionptr might be 32 or 64 bits.
    275      */
    276 
    277     SkFlattenable::Factory factory = NULL;
    278     if (flattenable) {
    279         factory = flattenable->getFactory();
    280     }
    281     if (NULL == factory) {
    282         if (fFactorySet != NULL || fNamedFactorySet != NULL) {
    283             this->write32(0);
    284         } else {
    285             this->writeFunctionPtr(NULL);
    286         }
    287         return;
    288     }
    289 
    290     /*
    291      *  We can write 1 of 3 versions of the flattenable:
    292      *  1.  function-ptr : this is the fastest for the reader, but assumes that
    293      *      the writer and reader are in the same process.
    294      *  2.  index into fFactorySet : This is assumes the writer will later
    295      *      resolve the function-ptrs into strings for its reader. SkPicture
    296      *      does exactly this, by writing a table of names (matching the indices)
    297      *      up front in its serialized form.
    298      *  3.  index into fNamedFactorySet. fNamedFactorySet will also store the
    299      *      name. SkGPipe uses this technique so it can write the name to its
    300      *      stream before writing the flattenable.
    301      */
    302     if (fFactorySet) {
    303         this->write32(fFactorySet->add(factory));
    304     } else if (fNamedFactorySet) {
    305         int32_t index = fNamedFactorySet->find(factory);
    306         this->write32(index);
    307         if (0 == index) {
    308             return;
    309         }
    310     } else {
    311         this->writeFunctionPtr((void*)factory);
    312     }
    313 
    314     // make room for the size of the flattened object
    315     (void)fWriter.reserve(sizeof(uint32_t));
    316     // record the current size, so we can subtract after the object writes.
    317     uint32_t offset = fWriter.size();
    318     // now flatten the object
    319     flattenObject(flattenable, *this);
    320     uint32_t objSize = fWriter.size() - offset;
    321     // record the obj's size
    322     *fWriter.peek32(offset - sizeof(uint32_t)) = objSize;
    323 }
    324