Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2011 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 #include "SkFlattenable.h"
      9 #include "SkTypeface.h"
     10 
     11 #include "SkMatrix.h"
     12 #include "SkRegion.h"
     13 
     14 void SkReadMatrix(SkReader32* reader, SkMatrix* matrix) {
     15     size_t size = matrix->unflatten(reader->peek());
     16     SkASSERT(SkAlign4(size) == size);
     17     (void)reader->skip(size);
     18 }
     19 
     20 void SkWriteMatrix(SkWriter32* writer, const SkMatrix& matrix) {
     21     size_t size = matrix.flatten(NULL);
     22     SkASSERT(SkAlign4(size) == size);
     23     matrix.flatten(writer->reserve(size));
     24 }
     25 
     26 void SkReadRegion(SkReader32* reader, SkRegion* rgn) {
     27     size_t size = rgn->unflatten(reader->peek());
     28     SkASSERT(SkAlign4(size) == size);
     29     (void)reader->skip(size);
     30 }
     31 
     32 void SkWriteRegion(SkWriter32* writer, const SkRegion& rgn) {
     33     size_t size = rgn.flatten(NULL);
     34     SkASSERT(SkAlign4(size) == size);
     35     rgn.flatten(writer->reserve(size));
     36 }
     37 
     38 ///////////////////////////////////////////////////////////////////////////////
     39 
     40 void SkFlattenable::flatten(SkFlattenableWriteBuffer&)
     41 {
     42     /*  we don't write anything at the moment, but this allows our subclasses
     43         to not know that, since we want them to always call INHERITED::flatten()
     44         in their code.
     45     */
     46 }
     47 
     48 ///////////////////////////////////////////////////////////////////////////////
     49 ///////////////////////////////////////////////////////////////////////////////
     50 
     51 SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
     52     fRCArray = NULL;
     53     fRCCount = 0;
     54 
     55     fTFArray = NULL;
     56     fTFCount = 0;
     57 
     58     fFactoryTDArray = NULL;
     59     fFactoryArray = NULL;
     60     fFactoryCount = 0;
     61     fPictureVersion = PICTURE_VERSION_JB;
     62 }
     63 
     64 SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data) :
     65         INHERITED(data, 1024 * 1024) {
     66     fRCArray = NULL;
     67     fRCCount = 0;
     68 
     69     fTFArray = NULL;
     70     fTFCount = 0;
     71 
     72     fFactoryTDArray = NULL;
     73     fFactoryArray = NULL;
     74     fFactoryCount = 0;
     75     fPictureVersion = PICTURE_VERSION_JB;
     76 }
     77 
     78 SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data, size_t size)
     79         : INHERITED(data, size) {
     80     fRCArray = NULL;
     81     fRCCount = 0;
     82 
     83     fTFArray = NULL;
     84     fTFCount = 0;
     85 
     86     fFactoryTDArray = NULL;
     87     fFactoryArray = NULL;
     88     fFactoryCount = 0;
     89     fPictureVersion = PICTURE_VERSION_JB;
     90 }
     91 
     92 SkTypeface* SkFlattenableReadBuffer::readTypeface() {
     93     uint32_t index = this->readU32();
     94     if (0 == index || index > (unsigned)fTFCount) {
     95         if (index) {
     96             SkDebugf("====== typeface index %d\n", index);
     97         }
     98         return NULL;
     99     } else {
    100         SkASSERT(fTFArray);
    101         return fTFArray[index - 1];
    102     }
    103 }
    104 
    105 SkRefCnt* SkFlattenableReadBuffer::readRefCnt() {
    106     uint32_t index = this->readU32();
    107     if (0 == index || index > (unsigned)fRCCount) {
    108         return NULL;
    109     } else {
    110         SkASSERT(fRCArray);
    111         return fRCArray[index - 1];
    112     }
    113 }
    114 
    115 SkFlattenable* SkFlattenableReadBuffer::readFlattenable() {
    116 
    117     if(fPictureVersion == PICTURE_VERSION_ICS) {
    118         SkFlattenable::Factory factory = NULL;
    119 
    120         if (fFactoryCount > 0) {
    121             uint32_t index = this->readU32();
    122             if (index > 0) {
    123                 index -= 1;
    124                 SkASSERT(index < (unsigned)fFactoryCount);
    125                 factory = fFactoryArray[index];
    126                 // if we recorded an index, but failed to get a factory, we need
    127                 // to skip the flattened data in the buffer
    128                 if (NULL == factory) {
    129                     uint32_t size = this->readU32();
    130                     this->skip(size);
    131                     // fall through and return NULL for the object
    132                 }
    133             }
    134         } else {
    135             factory = (SkFlattenable::Factory)readFunctionPtr();
    136         }
    137 
    138         SkFlattenable* obj = NULL;
    139         if (factory) {
    140             uint32_t sizeRecorded = this->readU32();
    141             uint32_t offset = this->offset();
    142             obj = (*factory)(*this);
    143             // check that we read the amount we expected
    144             uint32_t sizeRead = this->offset() - offset;
    145             if (sizeRecorded != sizeRead) {
    146                 // we could try to fix up the offset...
    147                 sk_throw();
    148             }
    149         }
    150         return obj;
    151     }
    152 
    153     SkFlattenable::Factory factory = NULL;
    154 
    155     if (fFactoryCount > 0) {
    156         int32_t index = this->readU32();
    157         if (0 == index) {
    158             return NULL; // writer failed to give us the flattenable
    159         }
    160         index = -index; // we stored the negative of the index
    161         index -= 1;     // we stored the index-base-1
    162         SkASSERT(index < fFactoryCount);
    163         factory = fFactoryArray[index];
    164     } else if (fFactoryTDArray) {
    165         const int32_t* peek = (const int32_t*)this->peek();
    166         if (*peek <= 0) {
    167             int32_t index = this->readU32();
    168             if (0 == index) {
    169                 return NULL; // writer failed to give us the flattenable
    170             }
    171             index = -index; // we stored the negative of the index
    172             index -= 1;     // we stored the index-base-1
    173             factory = (*fFactoryTDArray)[index];
    174         } else {
    175             const char* name = this->readString();
    176             factory = SkFlattenable::NameToFactory(name);
    177             if (factory) {
    178                 SkASSERT(fFactoryTDArray->find(factory) < 0);
    179                 *fFactoryTDArray->append() = factory;
    180             } else {
    181 //                SkDebugf("can't find factory for [%s]\n", name);
    182             }
    183             // if we didn't find a factory, that's our failure, not the writer's,
    184             // so we fall through, so we can skip the sizeRecorded data.
    185         }
    186     } else {
    187         factory = (SkFlattenable::Factory)readFunctionPtr();
    188         if (NULL == factory) {
    189             return NULL; // writer failed to give us the flattenable
    190         }
    191     }
    192 
    193     // if we get here, factory may still be null, but if that is the case, the
    194     // failure was ours, not the writer.
    195     SkFlattenable* obj = NULL;
    196     uint32_t sizeRecorded = this->readU32();
    197     if (factory) {
    198         uint32_t offset = this->offset();
    199         obj = (*factory)(*this);
    200         // check that we read the amount we expected
    201         uint32_t sizeRead = this->offset() - offset;
    202         if (sizeRecorded != sizeRead) {
    203             // we could try to fix up the offset...
    204             sk_throw();
    205         }
    206     } else {
    207         // we must skip the remaining data
    208         this->skip(sizeRecorded);
    209     }
    210     return obj;
    211 }
    212 
    213 void* SkFlattenableReadBuffer::readFunctionPtr() {
    214     void* proc;
    215     this->read(&proc, sizeof(proc));
    216     return proc;
    217 }
    218 
    219 ///////////////////////////////////////////////////////////////////////////////
    220 
    221 SkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) :
    222         INHERITED(minSize) {
    223     fFlags = (Flags)0;
    224     fRCSet = NULL;
    225     fTFSet = NULL;
    226     fFactorySet = NULL;
    227 }
    228 
    229 SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
    230     SkSafeUnref(fRCSet);
    231     SkSafeUnref(fTFSet);
    232     SkSafeUnref(fFactorySet);
    233 }
    234 
    235 SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
    236     SkRefCnt_SafeAssign(fRCSet, rec);
    237     return rec;
    238 }
    239 
    240 SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
    241     SkRefCnt_SafeAssign(fTFSet, rec);
    242     return rec;
    243 }
    244 
    245 SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
    246     SkRefCnt_SafeAssign(fFactorySet, rec);
    247     return rec;
    248 }
    249 
    250 void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) {
    251     if (NULL == obj || NULL == fTFSet) {
    252         this->write32(0);
    253     } else {
    254         this->write32(fTFSet->add(obj));
    255     }
    256 }
    257 
    258 void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) {
    259     if (NULL == obj || NULL == fRCSet) {
    260         this->write32(0);
    261     } else {
    262         this->write32(fRCSet->add(obj));
    263     }
    264 }
    265 
    266 void SkFlattenableWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
    267     /*
    268      *  If we have a factoryset, then the first 32bits tell us...
    269      *       0: failure to write the flattenable
    270      *      <0: we store the negative of the (1-based) index
    271      *      >0: the length of the name
    272      *  If we don't have a factoryset, then the first "ptr" is either the
    273      *  factory, or null for failure.
    274      *
    275      *  The distinction is important, since 0-index is 32bits (always), but a
    276      *  0-functionptr might be 32 or 64 bits.
    277      */
    278 
    279     SkFlattenable::Factory factory = NULL;
    280     if (flattenable) {
    281         factory = flattenable->getFactory();
    282     }
    283     if (NULL == factory) {
    284         if (fFactorySet) {
    285             this->write32(0);
    286         } else {
    287             this->writeFunctionPtr(NULL);
    288         }
    289         return;
    290     }
    291 
    292     /*
    293      *  We can write 1 of 3 versions of the flattenable:
    294      *  1.  function-ptr : this is the fastest for the reader, but assumes that
    295      *      the writer and reader are in the same process.
    296      *  2.  index into fFactorySet : This is assumes the writer will later
    297      *      resolve the function-ptrs into strings for its reader. SkPicture
    298      *      does exactly this, by writing a table of names (matching the indices)
    299      *      up front in its serialized form.
    300      *  3.  names : Reuse fFactorySet to store indices, but only after we've
    301      *      written the name the first time. SkGPipe uses this technique, as it
    302      *      doesn't require the reader to be told to know the table of names
    303      *      up front.
    304      */
    305     if (fFactorySet) {
    306         if (this->inlineFactoryNames()) {
    307             int index = fFactorySet->find(factory);
    308             if (index) {
    309                 // we write the negative of the index, to distinguish it from
    310                 // the length of a string
    311                 this->write32(-index);
    312             } else {
    313                 const char* name = SkFlattenable::FactoryToName(factory);
    314                 if (NULL == name) {
    315                     this->write32(0);
    316                     return;
    317                 }
    318                 this->writeString(name);
    319                 index = fFactorySet->add(factory);
    320             }
    321         } else {
    322             // we write the negative of the index, to distinguish it from
    323             // the length of a string
    324             this->write32(-(int)fFactorySet->add(factory));
    325         }
    326     } else {
    327         this->writeFunctionPtr((void*)factory);
    328     }
    329 
    330     // make room for the size of the flatttened object
    331     (void)this->reserve(sizeof(uint32_t));
    332     // record the current size, so we can subtract after the object writes.
    333     uint32_t offset = this->size();
    334     // now flatten the object
    335     flattenable->flatten(*this);
    336     uint32_t objSize = this->size() - offset;
    337     // record the obj's size
    338     *this->peek32(offset - sizeof(uint32_t)) = objSize;
    339 }
    340 
    341 void SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) {
    342     *(void**)this->reserve(sizeof(void*)) = proc;
    343 }
    344 
    345 ///////////////////////////////////////////////////////////////////////////////
    346 
    347 SkRefCntSet::~SkRefCntSet() {
    348     // call this now, while our decPtr() is sill in scope
    349     this->reset();
    350 }
    351 
    352 void SkRefCntSet::incPtr(void* ptr) {
    353     ((SkRefCnt*)ptr)->ref();
    354 }
    355 
    356 void SkRefCntSet::decPtr(void* ptr) {
    357     ((SkRefCnt*)ptr)->unref();
    358 }
    359 
    360 ///////////////////////////////////////////////////////////////////////////////
    361 ///////////////////////////////////////////////////////////////////////////////
    362 ///////////////////////////////////////////////////////////////////////////////
    363 
    364 #define MAX_PAIR_COUNT  64
    365 
    366 struct Pair {
    367     const char*             fName;
    368     SkFlattenable::Factory  fFactory;
    369 };
    370 
    371 static int gCount;
    372 static Pair gPairs[MAX_PAIR_COUNT];
    373 
    374 void SkFlattenable::Register(const char name[], Factory factory) {
    375     SkASSERT(name);
    376     SkASSERT(factory);
    377 
    378     static bool gOnce;
    379     if (!gOnce) {
    380         gCount = 0;
    381         gOnce = true;
    382     }
    383 
    384     SkASSERT(gCount < MAX_PAIR_COUNT);
    385 
    386     gPairs[gCount].fName = name;
    387     gPairs[gCount].fFactory = factory;
    388     gCount += 1;
    389 }
    390 
    391 #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
    392 static void report_no_entries(const char* functionName) {
    393     if (!gCount) {
    394         SkDebugf("%s has no registered name/factory pairs."
    395                  " Call SkGraphics::Init() at process initialization time.",
    396                  functionName);
    397     }
    398 }
    399 #endif
    400 
    401 SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
    402 #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
    403     report_no_entries(__FUNCTION__);
    404 #endif
    405     const Pair* pairs = gPairs;
    406     for (int i = gCount - 1; i >= 0; --i) {
    407         if (strcmp(pairs[i].fName, name) == 0) {
    408             return pairs[i].fFactory;
    409         }
    410     }
    411     return NULL;
    412 }
    413 
    414 const char* SkFlattenable::FactoryToName(Factory fact) {
    415 #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
    416     report_no_entries(__FUNCTION__);
    417 #endif
    418     const Pair* pairs = gPairs;
    419     for (int i = gCount - 1; i >= 0; --i) {
    420         if (pairs[i].fFactory == fact) {
    421             return pairs[i].fName;
    422         }
    423     }
    424     return NULL;
    425 }
    426 
    427 bool SkFlattenable::toDumpString(SkString* str) const {
    428     return false;
    429 }
    430