LCOV - code coverage report
Current view: directory - gfx/skia/src/core - SkFlattenable.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 200 11 5.5 %
Date: 2012-06-02 Functions: 30 1 3.3 %

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

Generated by: LCOV version 1.7