Home | History | Annotate | Download | only in core
      1 /* libs/graphics/images/SkStream.cpp
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #include "SkStream.h"
     19 #include "SkFixed.h"
     20 #include "SkString.h"
     21 #include "SkOSFile.h"
     22 
     23 SkStream::~SkStream() {}
     24 
     25 const char* SkStream::getFileName()
     26 {
     27     // override in subclass if you represent a file
     28     return NULL;
     29 }
     30 
     31 const void* SkStream::getMemoryBase()
     32 {
     33     // override in subclass if you represent a memory block
     34     return NULL;
     35 }
     36 
     37 size_t SkStream::skip(size_t size)
     38 {
     39     /*  Check for size == 0, and just return 0. If we passed that
     40         to read(), it would interpret it as a request for the entire
     41         size of the stream.
     42     */
     43     return size ? this->read(NULL, size) : 0;
     44 }
     45 
     46 int8_t SkStream::readS8() {
     47     int8_t value;
     48     SkDEBUGCODE(size_t len =) this->read(&value, 1);
     49     SkASSERT(1 == len);
     50     return value;
     51 }
     52 
     53 int16_t SkStream::readS16() {
     54     int16_t value;
     55     SkDEBUGCODE(size_t len =) this->read(&value, 2);
     56     SkASSERT(2 == len);
     57     return value;
     58 }
     59 
     60 int32_t SkStream::readS32() {
     61     int32_t value;
     62     SkDEBUGCODE(size_t len =) this->read(&value, 4);
     63     SkASSERT(4 == len);
     64     return value;
     65 }
     66 
     67 SkScalar SkStream::readScalar() {
     68     SkScalar value;
     69     SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
     70     SkASSERT(sizeof(SkScalar) == len);
     71     return value;
     72 }
     73 
     74 size_t SkStream::readPackedUInt() {
     75     uint8_t byte;
     76     if (!this->read(&byte, 1)) {
     77         return 0;
     78     }
     79     if (byte != 0xFF) {
     80         return byte;
     81     }
     82 
     83     uint16_t word;
     84     if (!this->read(&word, 2)) {
     85         return 0;
     86     }
     87     if (word != 0xFFFF) {
     88         return word;
     89     }
     90 
     91     uint32_t quad;
     92     if (!this->read(&quad, 4)) {
     93         return 0;
     94     }
     95     return quad;
     96 }
     97 
     98 //////////////////////////////////////////////////////////////////////////////////////
     99 
    100 SkWStream::~SkWStream()
    101 {
    102 }
    103 
    104 void SkWStream::newline()
    105 {
    106     this->write("\n", 1);
    107 }
    108 
    109 void SkWStream::flush()
    110 {
    111 }
    112 
    113 bool SkWStream::writeText(const char text[])
    114 {
    115     SkASSERT(text);
    116     return this->write(text, strlen(text));
    117 }
    118 
    119 bool SkWStream::writeDecAsText(int32_t dec)
    120 {
    121     SkString    tmp;
    122     tmp.appendS32(dec);
    123     return this->write(tmp.c_str(), tmp.size());
    124 }
    125 
    126 bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
    127 {
    128     SkString    tmp;
    129     tmp.appendS64(dec, minDigits);
    130     return this->write(tmp.c_str(), tmp.size());
    131 }
    132 
    133 bool SkWStream::writeHexAsText(uint32_t hex, int digits)
    134 {
    135     SkString    tmp;
    136     tmp.appendHex(hex, digits);
    137     return this->write(tmp.c_str(), tmp.size());
    138 }
    139 
    140 bool SkWStream::writeScalarAsText(SkScalar value)
    141 {
    142     SkString    tmp;
    143     tmp.appendScalar(value);
    144     return this->write(tmp.c_str(), tmp.size());
    145 }
    146 
    147 bool SkWStream::write8(U8CPU value) {
    148     uint8_t v = SkToU8(value);
    149     return this->write(&v, 1);
    150 }
    151 
    152 bool SkWStream::write16(U16CPU value) {
    153     uint16_t v = SkToU16(value);
    154     return this->write(&v, 2);
    155 }
    156 
    157 bool SkWStream::write32(uint32_t value) {
    158     return this->write(&value, 4);
    159 }
    160 
    161 bool SkWStream::writeScalar(SkScalar value) {
    162     return this->write(&value, sizeof(value));
    163 }
    164 
    165 bool SkWStream::writePackedUInt(size_t value) {
    166     if (value < 0xFF) {
    167         return this->write8(value);
    168     } else if (value < 0xFFFF) {
    169         return this->write8(0xFF) && this->write16(value);
    170     } else {
    171         return this->write16(0xFFFF) && this->write32(value);
    172     }
    173 }
    174 
    175 bool SkWStream::writeStream(SkStream* stream, size_t length) {
    176     char scratch[1024];
    177     const size_t MAX = sizeof(scratch);
    178 
    179     while (length != 0) {
    180         size_t n = length;
    181         if (n > MAX) {
    182             n = MAX;
    183         }
    184         stream->read(scratch, n);
    185         if (!this->write(scratch, n)) {
    186             return false;
    187         }
    188         length -= n;
    189     }
    190     return true;
    191 }
    192 
    193 ////////////////////////////////////////////////////////////////////////////
    194 
    195 SkFILEStream::SkFILEStream(const char file[]) : fName(file)
    196 {
    197     fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
    198 }
    199 
    200 SkFILEStream::~SkFILEStream()
    201 {
    202     if (fFILE)
    203         sk_fclose(fFILE);
    204 }
    205 
    206 void SkFILEStream::setPath(const char path[])
    207 {
    208     fName.set(path);
    209     if (fFILE)
    210     {
    211         sk_fclose(fFILE);
    212         fFILE = NULL;
    213     }
    214     if (path)
    215         fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
    216 }
    217 
    218 const char* SkFILEStream::getFileName()
    219 {
    220     return fName.c_str();
    221 }
    222 
    223 bool SkFILEStream::rewind()
    224 {
    225     if (fFILE)
    226     {
    227         if (sk_frewind(fFILE))
    228             return true;
    229         // we hit an error
    230         sk_fclose(fFILE);
    231         fFILE = NULL;
    232     }
    233     return false;
    234 }
    235 
    236 size_t SkFILEStream::read(void* buffer, size_t size)
    237 {
    238     if (fFILE)
    239     {
    240         if (buffer == NULL && size == 0)    // special signature, they want the total size
    241             return sk_fgetsize(fFILE);
    242         else
    243             return sk_fread(buffer, size, fFILE);
    244     }
    245     return 0;
    246 }
    247 
    248 ////////////////////////////////////////////////////////////////////////////
    249 
    250 SkMemoryStream::SkMemoryStream()
    251 {
    252     fWeOwnTheData = false;
    253     this->setMemory(NULL, 0);
    254 }
    255 
    256 SkMemoryStream::SkMemoryStream(size_t size) {
    257     fWeOwnTheData = true;
    258     fOffset = 0;
    259     fSize = size;
    260     fSrc = sk_malloc_throw(size);
    261 }
    262 
    263 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData)
    264 {
    265     fWeOwnTheData = false;
    266     this->setMemory(src, size, copyData);
    267 }
    268 
    269 SkMemoryStream::~SkMemoryStream()
    270 {
    271     if (fWeOwnTheData)
    272         sk_free((void*)fSrc);
    273 }
    274 
    275 void SkMemoryStream::setMemoryOwned(const void* src, size_t size)
    276 {
    277     if (fWeOwnTheData)
    278         sk_free((void*)fSrc);
    279 
    280     fSize = size;
    281     fOffset = 0;
    282     fWeOwnTheData = true;
    283 
    284     fSrc = src;
    285 }
    286 
    287 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData)
    288 {
    289     if (fWeOwnTheData)
    290         sk_free((void*)fSrc);
    291 
    292     fSize = size;
    293     fOffset = 0;
    294     fWeOwnTheData = copyData;
    295 
    296     if (copyData)
    297     {
    298         void* copy = sk_malloc_throw(size);
    299         memcpy(copy, src, size);
    300         src = copy;
    301     }
    302     fSrc = src;
    303 }
    304 
    305 void SkMemoryStream::skipToAlign4()
    306 {
    307     // cast to remove unary-minus warning
    308     fOffset += -(int)fOffset & 0x03;
    309 }
    310 
    311 bool SkMemoryStream::rewind()
    312 {
    313     fOffset = 0;
    314     return true;
    315 }
    316 
    317 size_t SkMemoryStream::read(void* buffer, size_t size)
    318 {
    319     if (buffer == NULL && size == 0)    // special signature, they want the total size
    320         return fSize;
    321 
    322     // if buffer is NULL, seek ahead by size
    323 
    324     if (size == 0)
    325         return 0;
    326     if (size > fSize - fOffset)
    327         size = fSize - fOffset;
    328     if (buffer) {
    329         memcpy(buffer, (const char*)fSrc + fOffset, size);
    330     }
    331     fOffset += size;
    332     return size;
    333 }
    334 
    335 const void* SkMemoryStream::getMemoryBase()
    336 {
    337     return fSrc;
    338 }
    339 
    340 const void* SkMemoryStream::getAtPos()
    341 {
    342     return (const char*)fSrc + fOffset;
    343 }
    344 
    345 size_t SkMemoryStream::seek(size_t offset)
    346 {
    347     if (offset > fSize)
    348         offset = fSize;
    349     fOffset = offset;
    350     return offset;
    351 }
    352 
    353 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    354 
    355 SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize)
    356     : fProxy(proxy)
    357 {
    358     SkASSERT(proxy != NULL);
    359     proxy->ref();
    360     this->init(NULL, bufferSize);
    361 }
    362 
    363 SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize)
    364     : fProxy(proxy)
    365 {
    366     SkASSERT(proxy != NULL);
    367     SkASSERT(buffer == NULL || bufferSize != 0);    // init(addr, 0) makes no sense, we must know how big their buffer is
    368     proxy->ref();
    369     this->init(buffer, bufferSize);
    370 }
    371 
    372 void SkBufferStream::init(void* buffer, size_t bufferSize)
    373 {
    374     if (bufferSize == 0)
    375         bufferSize = kDefaultBufferSize;
    376 
    377     fOrigBufferSize = bufferSize;
    378     fBufferSize = bufferSize;
    379     fBufferOffset = bufferSize; // to trigger a reload on the first read()
    380 
    381     if (buffer == NULL)
    382     {
    383         fBuffer = (char*)sk_malloc_throw(fBufferSize);
    384         fWeOwnTheBuffer = true;
    385     }
    386     else
    387     {
    388         fBuffer = (char*)buffer;
    389         fWeOwnTheBuffer = false;
    390     }
    391 }
    392 
    393 SkBufferStream::~SkBufferStream()
    394 {
    395     fProxy->unref();
    396     if (fWeOwnTheBuffer)
    397         sk_free(fBuffer);
    398 }
    399 
    400 bool SkBufferStream::rewind()
    401 {
    402     fBufferOffset = fBufferSize = fOrigBufferSize;
    403     return fProxy->rewind();
    404 }
    405 
    406 const char* SkBufferStream::getFileName()
    407 {
    408     return fProxy->getFileName();
    409 }
    410 
    411 #ifdef SK_DEBUG
    412 //  #define SK_TRACE_BUFFERSTREAM
    413 #endif
    414 
    415 size_t SkBufferStream::read(void* buffer, size_t size) {
    416 #ifdef SK_TRACE_BUFFERSTREAM
    417     SkDebugf("Request %d", size);
    418 #endif
    419 
    420     if (buffer == NULL && size == 0) {
    421         return fProxy->read(buffer, size);    // requesting total size
    422     }
    423 
    424     if (0 == size) {
    425         return 0;
    426     }
    427 
    428     // skip size bytes
    429     if (NULL == buffer) {
    430         size_t remaining = fBufferSize - fBufferOffset;
    431         if (remaining >= size) {
    432             fBufferOffset += size;
    433             return size;
    434         }
    435         // if we get here, we are being asked to skip beyond our current buffer
    436         // so reset our offset to force a read next time, and skip the diff
    437         // in our proxy
    438         fBufferOffset = fOrigBufferSize;
    439         return remaining + fProxy->read(NULL, size - remaining);
    440     }
    441 
    442     size_t s = size;
    443     size_t actuallyRead = 0;
    444 
    445     // flush what we can from our fBuffer
    446     if (fBufferOffset < fBufferSize)
    447     {
    448         if (s > fBufferSize - fBufferOffset)
    449             s = fBufferSize - fBufferOffset;
    450         memcpy(buffer, fBuffer + fBufferOffset, s);
    451 #ifdef SK_TRACE_BUFFERSTREAM
    452         SkDebugf(" flush %d", s);
    453 #endif
    454         size -= s;
    455         fBufferOffset += s;
    456         buffer = (char*)buffer + s;
    457         actuallyRead = s;
    458     }
    459 
    460     // check if there is more to read
    461     if (size)
    462     {
    463         SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer
    464 
    465         if (size < fBufferSize) // lets try to read more than the request
    466         {
    467             s = fProxy->read(fBuffer, fBufferSize);
    468 #ifdef SK_TRACE_BUFFERSTREAM
    469             SkDebugf(" read %d into fBuffer", s);
    470 #endif
    471             if (size > s)   // they asked for too much
    472                 size = s;
    473             if (size)
    474             {
    475                 memcpy(buffer, fBuffer, size);
    476                 actuallyRead += size;
    477 #ifdef SK_TRACE_BUFFERSTREAM
    478                 SkDebugf(" memcpy %d into dst", size);
    479 #endif
    480             }
    481 
    482             fBufferOffset = size;
    483             fBufferSize = s;        // record the (possibly smaller) size for the buffer
    484         }
    485         else    // just do a direct read
    486         {
    487             actuallyRead += fProxy->read(buffer, size);
    488 #ifdef SK_TRACE_BUFFERSTREAM
    489             SkDebugf(" direct read %d", size);
    490 #endif
    491         }
    492     }
    493 #ifdef SK_TRACE_BUFFERSTREAM
    494     SkDebugf("\n");
    495 #endif
    496     return actuallyRead;
    497 }
    498 
    499 const void* SkBufferStream::getMemoryBase()
    500 {
    501     return fProxy->getMemoryBase();
    502 }
    503 
    504 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    505 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    506 
    507 SkFILEWStream::SkFILEWStream(const char path[])
    508 {
    509     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
    510 }
    511 
    512 SkFILEWStream::~SkFILEWStream()
    513 {
    514     if (fFILE)
    515         sk_fclose(fFILE);
    516 }
    517 
    518 bool SkFILEWStream::write(const void* buffer, size_t size)
    519 {
    520     if (fFILE == NULL)
    521         return false;
    522 
    523     if (sk_fwrite(buffer, size, fFILE) != size)
    524     {
    525         SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
    526         sk_fclose(fFILE);
    527         fFILE = NULL;
    528         return false;
    529     }
    530     return true;
    531 }
    532 
    533 void SkFILEWStream::flush()
    534 {
    535     if (fFILE)
    536         sk_fflush(fFILE);
    537 }
    538 
    539 ////////////////////////////////////////////////////////////////////////
    540 
    541 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
    542     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
    543 {
    544 }
    545 
    546 bool SkMemoryWStream::write(const void* buffer, size_t size)
    547 {
    548     size = SkMin32(size, fMaxLength - fBytesWritten);
    549     if (size > 0)
    550     {
    551         memcpy(fBuffer + fBytesWritten, buffer, size);
    552         fBytesWritten += size;
    553         return true;
    554     }
    555     return false;
    556 }
    557 
    558 ////////////////////////////////////////////////////////////////////////
    559 
    560 #define SkDynamicMemoryWStream_MinBlockSize   256
    561 
    562 struct SkDynamicMemoryWStream::Block {
    563     Block*  fNext;
    564     char*   fCurr;
    565     char*   fStop;
    566 
    567     const char* start() const { return (const char*)(this + 1); }
    568     char*   start() { return (char*)(this + 1); }
    569     size_t  avail() const { return fStop - fCurr; }
    570     size_t  written() const { return fCurr - this->start(); }
    571 
    572     void init(size_t size)
    573     {
    574         fNext = NULL;
    575         fCurr = this->start();
    576         fStop = this->start() + size;
    577     }
    578 
    579     const void* append(const void* data, size_t size)
    580     {
    581         SkASSERT((size_t)(fStop - fCurr) >= size);
    582         memcpy(fCurr, data, size);
    583         fCurr += size;
    584         return (const void*)((const char*)data + size);
    585     }
    586 };
    587 
    588 SkDynamicMemoryWStream::SkDynamicMemoryWStream() : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopyToCache(NULL)
    589 {
    590 }
    591 
    592 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
    593 {
    594     reset();
    595 }
    596 
    597 const char* SkDynamicMemoryWStream::detach()
    598 {
    599     const char* result = getStream();
    600     fCopyToCache = NULL;
    601     return result;
    602 }
    603 
    604 void SkDynamicMemoryWStream::reset()
    605 {
    606     sk_free(fCopyToCache);
    607     Block*  block = fHead;
    608 
    609     while (block != NULL) {
    610         Block*  next = block->fNext;
    611         sk_free(block);
    612         block = next;
    613     }
    614     fHead = fTail = NULL;
    615     fBytesWritten = 0;
    616     fCopyToCache = NULL;
    617 }
    618 
    619 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
    620 {
    621     if (count > 0) {
    622 
    623         if (fCopyToCache) {
    624             sk_free(fCopyToCache);
    625             fCopyToCache = NULL;
    626         }
    627         fBytesWritten += count;
    628 
    629         size_t  size;
    630 
    631         if (fTail != NULL && fTail->avail() > 0) {
    632             size = SkMin32(fTail->avail(), count);
    633             buffer = fTail->append(buffer, size);
    634             SkASSERT(count >= size);
    635             count -= size;
    636             if (count == 0)
    637                 return true;
    638         }
    639 
    640         size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
    641         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
    642         block->init(size);
    643         block->append(buffer, count);
    644 
    645         if (fTail != NULL)
    646             fTail->fNext = block;
    647         else
    648             fHead = fTail = block;
    649         fTail = block;
    650     }
    651     return true;
    652 }
    653 
    654 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
    655 {
    656     if (offset + count > fBytesWritten)
    657         return false; // test does not partially modify
    658     Block* block = fHead;
    659     while (block != NULL) {
    660         size_t size = block->written();
    661         if (offset < size) {
    662             size_t part = offset + count > size ? size - offset : count;
    663             memcpy(block->start() + offset, buffer, part);
    664             if (count <= part)
    665                 return true;
    666             count -= part;
    667             buffer = (const void*) ((char* ) buffer + part);
    668         }
    669         offset = offset > size ? offset - size : 0;
    670         block = block->fNext;
    671     }
    672     return false;
    673 }
    674 
    675 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
    676 {
    677     if (offset + count > fBytesWritten)
    678         return false; // test does not partially modify
    679     Block* block = fHead;
    680     while (block != NULL) {
    681         size_t size = block->written();
    682         if (offset < size) {
    683             size_t part = offset + count > size ? size - offset : count;
    684             memcpy(buffer, block->start() + offset, part);
    685             if (count <= part)
    686                 return true;
    687             count -= part;
    688             buffer = (void*) ((char* ) buffer + part);
    689         }
    690         offset = offset > size ? offset - size : 0;
    691         block = block->fNext;
    692     }
    693     return false;
    694 }
    695 
    696 void SkDynamicMemoryWStream::copyTo(void* dst) const
    697 {
    698     Block* block = fHead;
    699 
    700     while (block != NULL) {
    701         size_t size = block->written();
    702         memcpy(dst, block->start(), size);
    703         dst = (void*)((char*)dst + size);
    704         block = block->fNext;
    705     }
    706 }
    707 
    708 const char* SkDynamicMemoryWStream::getStream() const
    709 {
    710     if (fCopyToCache == NULL) {
    711         fCopyToCache = (char*)sk_malloc_throw(fBytesWritten);
    712         this->copyTo(fCopyToCache);
    713     }
    714     return fCopyToCache;
    715 }
    716 
    717 void SkDynamicMemoryWStream::padToAlign4()
    718 {
    719     // cast to remove unary-minus warning
    720     int padBytes = -(int)fBytesWritten & 0x03;
    721     if (padBytes == 0)
    722         return;
    723     int zero = 0;
    724     write(&zero, padBytes);
    725 }
    726 
    727 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    728 
    729 void SkDebugWStream::newline()
    730 {
    731 #ifdef SK_DEBUG
    732     SkDebugf("\n");
    733 #endif
    734 }
    735 
    736 bool SkDebugWStream::write(const void* buffer, size_t size)
    737 {
    738 #ifdef SK_DEBUG
    739     char* s = new char[size+1];
    740     memcpy(s, buffer, size);
    741     s[size] = 0;
    742     SkDebugf("%s", s);
    743     delete[] s;
    744 #endif
    745     return true;
    746 }
    747