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::writeHexAsText(uint32_t hex, int digits)
    127 {
    128     SkString    tmp;
    129     tmp.appendHex(hex, digits);
    130     return this->write(tmp.c_str(), tmp.size());
    131 }
    132 
    133 bool SkWStream::writeScalarAsText(SkScalar value)
    134 {
    135     SkString    tmp;
    136     tmp.appendScalar(value);
    137     return this->write(tmp.c_str(), tmp.size());
    138 }
    139 
    140 bool SkWStream::write8(U8CPU value) {
    141     uint8_t v = SkToU8(value);
    142     return this->write(&v, 1);
    143 }
    144 
    145 bool SkWStream::write16(U16CPU value) {
    146     uint16_t v = SkToU16(value);
    147     return this->write(&v, 2);
    148 }
    149 
    150 bool SkWStream::write32(uint32_t value) {
    151     return this->write(&value, 4);
    152 }
    153 
    154 bool SkWStream::writeScalar(SkScalar value) {
    155     return this->write(&value, sizeof(value));
    156 }
    157 
    158 bool SkWStream::writePackedUInt(size_t value) {
    159     if (value < 0xFF) {
    160         return this->write8(value);
    161     } else if (value < 0xFFFF) {
    162         return this->write8(0xFF) && this->write16(value);
    163     } else {
    164         return this->write16(0xFFFF) && this->write32(value);
    165     }
    166 }
    167 
    168 bool SkWStream::writeStream(SkStream* stream, size_t length) {
    169     char scratch[1024];
    170     const size_t MAX = sizeof(scratch);
    171 
    172     while (length != 0) {
    173         size_t n = length;
    174         if (n > MAX) {
    175             n = MAX;
    176         }
    177         stream->read(scratch, n);
    178         if (!this->write(scratch, n)) {
    179             return false;
    180         }
    181         length -= n;
    182     }
    183     return true;
    184 }
    185 
    186 ////////////////////////////////////////////////////////////////////////////
    187 
    188 SkFILEStream::SkFILEStream(const char file[]) : fName(file)
    189 {
    190     fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
    191 }
    192 
    193 SkFILEStream::~SkFILEStream()
    194 {
    195     if (fFILE)
    196         sk_fclose(fFILE);
    197 }
    198 
    199 void SkFILEStream::setPath(const char path[])
    200 {
    201     fName.set(path);
    202     if (fFILE)
    203     {
    204         sk_fclose(fFILE);
    205         fFILE = NULL;
    206     }
    207     if (path)
    208         fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
    209 }
    210 
    211 const char* SkFILEStream::getFileName()
    212 {
    213     return fName.c_str();
    214 }
    215 
    216 bool SkFILEStream::rewind()
    217 {
    218     if (fFILE)
    219     {
    220         if (sk_frewind(fFILE))
    221             return true;
    222         // we hit an error
    223         sk_fclose(fFILE);
    224         fFILE = NULL;
    225     }
    226     return false;
    227 }
    228 
    229 size_t SkFILEStream::read(void* buffer, size_t size)
    230 {
    231     if (fFILE)
    232     {
    233         if (buffer == NULL && size == 0)    // special signature, they want the total size
    234             return sk_fgetsize(fFILE);
    235         else
    236             return sk_fread(buffer, size, fFILE);
    237     }
    238     return 0;
    239 }
    240 
    241 ////////////////////////////////////////////////////////////////////////////
    242 
    243 SkMemoryStream::SkMemoryStream()
    244 {
    245     fWeOwnTheData = false;
    246     this->setMemory(NULL, 0);
    247 }
    248 
    249 SkMemoryStream::SkMemoryStream(size_t size) {
    250     fWeOwnTheData = true;
    251     fOffset = 0;
    252     fSize = size;
    253     fSrc = sk_malloc_throw(size);
    254 }
    255 
    256 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData)
    257 {
    258     fWeOwnTheData = false;
    259     this->setMemory(src, size, copyData);
    260 }
    261 
    262 SkMemoryStream::~SkMemoryStream()
    263 {
    264     if (fWeOwnTheData)
    265         sk_free((void*)fSrc);
    266 }
    267 
    268 void SkMemoryStream::setMemoryOwned(const void* src, size_t size)
    269 {
    270     if (fWeOwnTheData)
    271         sk_free((void*)fSrc);
    272 
    273     fSize = size;
    274     fOffset = 0;
    275     fWeOwnTheData = true;
    276 
    277     fSrc = src;
    278 }
    279 
    280 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData)
    281 {
    282     if (fWeOwnTheData)
    283         sk_free((void*)fSrc);
    284 
    285     fSize = size;
    286     fOffset = 0;
    287     fWeOwnTheData = copyData;
    288 
    289     if (copyData)
    290     {
    291         void* copy = sk_malloc_throw(size);
    292         memcpy(copy, src, size);
    293         src = copy;
    294     }
    295     fSrc = src;
    296 }
    297 
    298 void SkMemoryStream::skipToAlign4()
    299 {
    300     // cast to remove unary-minus warning
    301     fOffset += -(int)fOffset & 0x03;
    302 }
    303 
    304 bool SkMemoryStream::rewind()
    305 {
    306     fOffset = 0;
    307     return true;
    308 }
    309 
    310 size_t SkMemoryStream::read(void* buffer, size_t size)
    311 {
    312     if (buffer == NULL && size == 0)    // special signature, they want the total size
    313         return fSize;
    314 
    315     // if buffer is NULL, seek ahead by size
    316 
    317     if (size == 0)
    318         return 0;
    319     if (size > fSize - fOffset)
    320         size = fSize - fOffset;
    321     if (buffer) {
    322         memcpy(buffer, (const char*)fSrc + fOffset, size);
    323     }
    324     fOffset += size;
    325     return size;
    326 }
    327 
    328 const void* SkMemoryStream::getMemoryBase()
    329 {
    330     return fSrc;
    331 }
    332 
    333 const void* SkMemoryStream::getAtPos()
    334 {
    335     return (const char*)fSrc + fOffset;
    336 }
    337 
    338 size_t SkMemoryStream::seek(size_t offset)
    339 {
    340     if (offset > fSize)
    341         offset = fSize;
    342     fOffset = offset;
    343     return offset;
    344 }
    345 
    346 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    347 
    348 SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize)
    349     : fProxy(proxy)
    350 {
    351     SkASSERT(proxy != NULL);
    352     proxy->ref();
    353     this->init(NULL, bufferSize);
    354 }
    355 
    356 SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize)
    357     : fProxy(proxy)
    358 {
    359     SkASSERT(proxy != NULL);
    360     SkASSERT(buffer == NULL || bufferSize != 0);    // init(addr, 0) makes no sense, we must know how big their buffer is
    361     proxy->ref();
    362     this->init(buffer, bufferSize);
    363 }
    364 
    365 void SkBufferStream::init(void* buffer, size_t bufferSize)
    366 {
    367     if (bufferSize == 0)
    368         bufferSize = kDefaultBufferSize;
    369 
    370     fOrigBufferSize = bufferSize;
    371     fBufferSize = bufferSize;
    372     fBufferOffset = bufferSize; // to trigger a reload on the first read()
    373 
    374     if (buffer == NULL)
    375     {
    376         fBuffer = (char*)sk_malloc_throw(fBufferSize);
    377         fWeOwnTheBuffer = true;
    378     }
    379     else
    380     {
    381         fBuffer = (char*)buffer;
    382         fWeOwnTheBuffer = false;
    383     }
    384 }
    385 
    386 SkBufferStream::~SkBufferStream()
    387 {
    388     fProxy->unref();
    389     if (fWeOwnTheBuffer)
    390         sk_free(fBuffer);
    391 }
    392 
    393 bool SkBufferStream::rewind()
    394 {
    395     fBufferOffset = fBufferSize = fOrigBufferSize;
    396     return fProxy->rewind();
    397 }
    398 
    399 const char* SkBufferStream::getFileName()
    400 {
    401     return fProxy->getFileName();
    402 }
    403 
    404 #ifdef SK_DEBUG
    405 //  #define SK_TRACE_BUFFERSTREAM
    406 #endif
    407 
    408 size_t SkBufferStream::read(void* buffer, size_t size) {
    409 #ifdef SK_TRACE_BUFFERSTREAM
    410     SkDebugf("Request %d", size);
    411 #endif
    412 
    413     if (buffer == NULL && size == 0) {
    414         return fProxy->read(buffer, size);    // requesting total size
    415     }
    416 
    417     if (0 == size) {
    418         return 0;
    419     }
    420 
    421     // skip size bytes
    422     if (NULL == buffer) {
    423         size_t remaining = fBufferSize - fBufferOffset;
    424         if (remaining >= size) {
    425             fBufferOffset += size;
    426             return size;
    427         }
    428         // if we get here, we are being asked to skip beyond our current buffer
    429         // so reset our offset to force a read next time, and skip the diff
    430         // in our proxy
    431         fBufferOffset = fOrigBufferSize;
    432         return remaining + fProxy->read(NULL, size - remaining);
    433     }
    434 
    435     size_t s = size;
    436     size_t actuallyRead = 0;
    437 
    438     // flush what we can from our fBuffer
    439     if (fBufferOffset < fBufferSize)
    440     {
    441         if (s > fBufferSize - fBufferOffset)
    442             s = fBufferSize - fBufferOffset;
    443         memcpy(buffer, fBuffer + fBufferOffset, s);
    444 #ifdef SK_TRACE_BUFFERSTREAM
    445         SkDebugf(" flush %d", s);
    446 #endif
    447         size -= s;
    448         fBufferOffset += s;
    449         buffer = (char*)buffer + s;
    450         actuallyRead = s;
    451     }
    452 
    453     // check if there is more to read
    454     if (size)
    455     {
    456         SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer
    457 
    458         if (size < fBufferSize) // lets try to read more than the request
    459         {
    460             s = fProxy->read(fBuffer, fBufferSize);
    461 #ifdef SK_TRACE_BUFFERSTREAM
    462             SkDebugf(" read %d into fBuffer", s);
    463 #endif
    464             if (size > s)   // they asked for too much
    465                 size = s;
    466             if (size)
    467             {
    468                 memcpy(buffer, fBuffer, size);
    469                 actuallyRead += size;
    470 #ifdef SK_TRACE_BUFFERSTREAM
    471                 SkDebugf(" memcpy %d into dst", size);
    472 #endif
    473             }
    474 
    475             fBufferOffset = size;
    476             fBufferSize = s;        // record the (possibly smaller) size for the buffer
    477         }
    478         else    // just do a direct read
    479         {
    480             actuallyRead += fProxy->read(buffer, size);
    481 #ifdef SK_TRACE_BUFFERSTREAM
    482             SkDebugf(" direct read %d", size);
    483 #endif
    484         }
    485     }
    486 #ifdef SK_TRACE_BUFFERSTREAM
    487     SkDebugf("\n");
    488 #endif
    489     return actuallyRead;
    490 }
    491 
    492 const void* SkBufferStream::getMemoryBase()
    493 {
    494     return fProxy->getMemoryBase();
    495 }
    496 
    497 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    498 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    499 
    500 SkFILEWStream::SkFILEWStream(const char path[])
    501 {
    502     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
    503 }
    504 
    505 SkFILEWStream::~SkFILEWStream()
    506 {
    507     if (fFILE)
    508         sk_fclose(fFILE);
    509 }
    510 
    511 bool SkFILEWStream::write(const void* buffer, size_t size)
    512 {
    513     if (fFILE == NULL)
    514         return false;
    515 
    516     if (sk_fwrite(buffer, size, fFILE) != size)
    517     {
    518         SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
    519         sk_fclose(fFILE);
    520         fFILE = NULL;
    521         return false;
    522     }
    523     return true;
    524 }
    525 
    526 void SkFILEWStream::flush()
    527 {
    528     if (fFILE)
    529         sk_fflush(fFILE);
    530 }
    531 
    532 ////////////////////////////////////////////////////////////////////////
    533 
    534 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
    535     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
    536 {
    537 }
    538 
    539 bool SkMemoryWStream::write(const void* buffer, size_t size)
    540 {
    541     size = SkMin32(size, fMaxLength - fBytesWritten);
    542     if (size > 0)
    543     {
    544         memcpy(fBuffer + fBytesWritten, buffer, size);
    545         fBytesWritten += size;
    546         return true;
    547     }
    548     return false;
    549 }
    550 
    551 ////////////////////////////////////////////////////////////////////////
    552 
    553 #define SkDynamicMemoryWStream_MinBlockSize   256
    554 
    555 struct SkDynamicMemoryWStream::Block {
    556     Block*  fNext;
    557     char*   fCurr;
    558     char*   fStop;
    559 
    560     const char* start() const { return (const char*)(this + 1); }
    561     char*   start() { return (char*)(this + 1); }
    562     size_t  avail() const { return fStop - fCurr; }
    563     size_t  written() const { return fCurr - this->start(); }
    564 
    565     void init(size_t size)
    566     {
    567         fNext = NULL;
    568         fCurr = this->start();
    569         fStop = this->start() + size;
    570     }
    571 
    572     const void* append(const void* data, size_t size)
    573     {
    574         SkASSERT((size_t)(fStop - fCurr) >= size);
    575         memcpy(fCurr, data, size);
    576         fCurr += size;
    577         return (const void*)((const char*)data + size);
    578     }
    579 };
    580 
    581 SkDynamicMemoryWStream::SkDynamicMemoryWStream() : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopyToCache(NULL)
    582 {
    583 }
    584 
    585 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
    586 {
    587     reset();
    588 }
    589 
    590 const char* SkDynamicMemoryWStream::detach()
    591 {
    592     const char* result = getStream();
    593     fCopyToCache = NULL;
    594     return result;
    595 }
    596 
    597 void SkDynamicMemoryWStream::reset()
    598 {
    599     sk_free(fCopyToCache);
    600     Block*  block = fHead;
    601 
    602     while (block != NULL) {
    603         Block*  next = block->fNext;
    604         sk_free(block);
    605         block = next;
    606     }
    607     fHead = fTail = NULL;
    608     fBytesWritten = 0;
    609     fCopyToCache = NULL;
    610 }
    611 
    612 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
    613 {
    614     if (count > 0) {
    615 
    616         if (fCopyToCache) {
    617             sk_free(fCopyToCache);
    618             fCopyToCache = NULL;
    619         }
    620         fBytesWritten += count;
    621 
    622         size_t  size;
    623 
    624         if (fTail != NULL && fTail->avail() > 0) {
    625             size = SkMin32(fTail->avail(), count);
    626             buffer = fTail->append(buffer, size);
    627             SkASSERT(count >= size);
    628             count -= size;
    629             if (count == 0)
    630                 return true;
    631         }
    632 
    633         size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
    634         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
    635         block->init(size);
    636         block->append(buffer, count);
    637 
    638         if (fTail != NULL)
    639             fTail->fNext = block;
    640         else
    641             fHead = fTail = block;
    642         fTail = block;
    643     }
    644     return true;
    645 }
    646 
    647 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
    648 {
    649     if (offset + count > fBytesWritten)
    650         return false; // test does not partially modify
    651     Block* block = fHead;
    652     while (block != NULL) {
    653         size_t size = block->written();
    654         if (offset < size) {
    655             size_t part = offset + count > size ? size - offset : count;
    656             memcpy(block->start() + offset, buffer, part);
    657             if (count <= part)
    658                 return true;
    659             count -= part;
    660             buffer = (const void*) ((char* ) buffer + part);
    661         }
    662         offset = offset > size ? offset - size : 0;
    663         block = block->fNext;
    664     }
    665     return false;
    666 }
    667 
    668 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
    669 {
    670     if (offset + count > fBytesWritten)
    671         return false; // test does not partially modify
    672     Block* block = fHead;
    673     while (block != NULL) {
    674         size_t size = block->written();
    675         if (offset < size) {
    676             size_t part = offset + count > size ? size - offset : count;
    677             memcpy(buffer, block->start() + offset, part);
    678             if (count <= part)
    679                 return true;
    680             count -= part;
    681             buffer = (void*) ((char* ) buffer + part);
    682         }
    683         offset = offset > size ? offset - size : 0;
    684         block = block->fNext;
    685     }
    686     return false;
    687 }
    688 
    689 void SkDynamicMemoryWStream::copyTo(void* dst) const
    690 {
    691     Block* block = fHead;
    692 
    693     while (block != NULL) {
    694         size_t size = block->written();
    695         memcpy(dst, block->start(), size);
    696         dst = (void*)((char*)dst + size);
    697         block = block->fNext;
    698     }
    699 }
    700 
    701 const char* SkDynamicMemoryWStream::getStream() const
    702 {
    703     if (fCopyToCache == NULL) {
    704         fCopyToCache = (char*)sk_malloc_throw(fBytesWritten);
    705         this->copyTo(fCopyToCache);
    706     }
    707     return fCopyToCache;
    708 }
    709 
    710 void SkDynamicMemoryWStream::padToAlign4()
    711 {
    712     // cast to remove unary-minus warning
    713     int padBytes = -(int)fBytesWritten & 0x03;
    714     if (padBytes == 0)
    715         return;
    716     int zero = 0;
    717     write(&zero, padBytes);
    718 }
    719 
    720 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    721 
    722 void SkDebugWStream::newline()
    723 {
    724 #ifdef SK_DEBUG
    725     SkDebugf("\n");
    726 #endif
    727 }
    728 
    729 bool SkDebugWStream::write(const void* buffer, size_t size)
    730 {
    731 #ifdef SK_DEBUG
    732     char* s = new char[size+1];
    733     memcpy(s, buffer, size);
    734     s[size] = 0;
    735     SkDebugf("%s", s);
    736     delete[] s;
    737 #endif
    738     return true;
    739 }
    740 
    741