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