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::setMemory(const void* src, size_t size, bool copyData)
    269 {
    270     if (fWeOwnTheData)
    271         sk_free((void*)fSrc);
    272 
    273     fSize = size;
    274     fOffset = 0;
    275     fWeOwnTheData = copyData;
    276 
    277     if (copyData)
    278     {
    279         void* copy = sk_malloc_throw(size);
    280         memcpy(copy, src, size);
    281         src = copy;
    282     }
    283     fSrc = src;
    284 }
    285 
    286 void SkMemoryStream::skipToAlign4()
    287 {
    288     // cast to remove unary-minus warning
    289     fOffset += -(int)fOffset & 0x03;
    290 }
    291 
    292 bool SkMemoryStream::rewind()
    293 {
    294     fOffset = 0;
    295     return true;
    296 }
    297 
    298 size_t SkMemoryStream::read(void* buffer, size_t size)
    299 {
    300     if (buffer == NULL && size == 0)    // special signature, they want the total size
    301         return fSize;
    302 
    303     // if buffer is NULL, seek ahead by size
    304 
    305     if (size == 0)
    306         return 0;
    307     if (size > fSize - fOffset)
    308         size = fSize - fOffset;
    309     if (buffer) {
    310         memcpy(buffer, (const char*)fSrc + fOffset, size);
    311     }
    312     fOffset += size;
    313     return size;
    314 }
    315 
    316 const void* SkMemoryStream::getMemoryBase()
    317 {
    318     return fSrc;
    319 }
    320 
    321 const void* SkMemoryStream::getAtPos()
    322 {
    323     return (const char*)fSrc + fOffset;
    324 }
    325 
    326 size_t SkMemoryStream::seek(size_t offset)
    327 {
    328     if (offset > fSize)
    329         offset = fSize;
    330     fOffset = offset;
    331     return offset;
    332 }
    333 
    334 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    335 
    336 SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize)
    337     : fProxy(proxy)
    338 {
    339     SkASSERT(proxy != NULL);
    340     proxy->ref();
    341     this->init(NULL, bufferSize);
    342 }
    343 
    344 SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize)
    345     : fProxy(proxy)
    346 {
    347     SkASSERT(proxy != NULL);
    348     SkASSERT(buffer == NULL || bufferSize != 0);    // init(addr, 0) makes no sense, we must know how big their buffer is
    349     proxy->ref();
    350     this->init(buffer, bufferSize);
    351 }
    352 
    353 void SkBufferStream::init(void* buffer, size_t bufferSize)
    354 {
    355     if (bufferSize == 0)
    356         bufferSize = kDefaultBufferSize;
    357 
    358     fOrigBufferSize = bufferSize;
    359     fBufferSize = bufferSize;
    360     fBufferOffset = bufferSize; // to trigger a reload on the first read()
    361 
    362     if (buffer == NULL)
    363     {
    364         fBuffer = (char*)sk_malloc_throw(fBufferSize);
    365         fWeOwnTheBuffer = true;
    366     }
    367     else
    368     {
    369         fBuffer = (char*)buffer;
    370         fWeOwnTheBuffer = false;
    371     }
    372 }
    373 
    374 SkBufferStream::~SkBufferStream()
    375 {
    376     fProxy->unref();
    377     if (fWeOwnTheBuffer)
    378         sk_free(fBuffer);
    379 }
    380 
    381 bool SkBufferStream::rewind()
    382 {
    383     fBufferOffset = fBufferSize = fOrigBufferSize;
    384     return fProxy->rewind();
    385 }
    386 
    387 const char* SkBufferStream::getFileName()
    388 {
    389     return fProxy->getFileName();
    390 }
    391 
    392 #ifdef SK_DEBUG
    393 //  #define SK_TRACE_BUFFERSTREAM
    394 #endif
    395 
    396 size_t SkBufferStream::read(void* buffer, size_t size) {
    397 #ifdef SK_TRACE_BUFFERSTREAM
    398     SkDebugf("Request %d", size);
    399 #endif
    400 
    401     if (buffer == NULL && size == 0) {
    402         return fProxy->read(buffer, size);    // requesting total size
    403     }
    404 
    405     if (0 == size) {
    406         return 0;
    407     }
    408 
    409     // skip size bytes
    410     if (NULL == buffer) {
    411         size_t remaining = fBufferSize - fBufferOffset;
    412         if (remaining >= size) {
    413             fBufferOffset += size;
    414             return size;
    415         }
    416         // if we get here, we are being asked to skip beyond our current buffer
    417         // so reset our offset to force a read next time, and skip the diff
    418         // in our proxy
    419         fBufferOffset = fOrigBufferSize;
    420         return remaining + fProxy->read(NULL, size - remaining);
    421     }
    422 
    423     size_t s = size;
    424     size_t actuallyRead = 0;
    425 
    426     // flush what we can from our fBuffer
    427     if (fBufferOffset < fBufferSize)
    428     {
    429         if (s > fBufferSize - fBufferOffset)
    430             s = fBufferSize - fBufferOffset;
    431         memcpy(buffer, fBuffer + fBufferOffset, s);
    432 #ifdef SK_TRACE_BUFFERSTREAM
    433         SkDebugf(" flush %d", s);
    434 #endif
    435         size -= s;
    436         fBufferOffset += s;
    437         buffer = (char*)buffer + s;
    438         actuallyRead = s;
    439     }
    440 
    441     // check if there is more to read
    442     if (size)
    443     {
    444         SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer
    445 
    446         if (size < fBufferSize) // lets try to read more than the request
    447         {
    448             s = fProxy->read(fBuffer, fBufferSize);
    449 #ifdef SK_TRACE_BUFFERSTREAM
    450             SkDebugf(" read %d into fBuffer", s);
    451 #endif
    452             if (size > s)   // they asked for too much
    453                 size = s;
    454             if (size)
    455             {
    456                 memcpy(buffer, fBuffer, size);
    457                 actuallyRead += size;
    458 #ifdef SK_TRACE_BUFFERSTREAM
    459                 SkDebugf(" memcpy %d into dst", size);
    460 #endif
    461             }
    462 
    463             fBufferOffset = size;
    464             fBufferSize = s;        // record the (possibly smaller) size for the buffer
    465         }
    466         else    // just do a direct read
    467         {
    468             actuallyRead += fProxy->read(buffer, size);
    469 #ifdef SK_TRACE_BUFFERSTREAM
    470             SkDebugf(" direct read %d", size);
    471 #endif
    472         }
    473     }
    474 #ifdef SK_TRACE_BUFFERSTREAM
    475     SkDebugf("\n");
    476 #endif
    477     return actuallyRead;
    478 }
    479 
    480 const void* SkBufferStream::getMemoryBase()
    481 {
    482     return fProxy->getMemoryBase();
    483 }
    484 
    485 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    486 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    487 
    488 SkFILEWStream::SkFILEWStream(const char path[])
    489 {
    490     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
    491 }
    492 
    493 SkFILEWStream::~SkFILEWStream()
    494 {
    495     if (fFILE)
    496         sk_fclose(fFILE);
    497 }
    498 
    499 bool SkFILEWStream::write(const void* buffer, size_t size)
    500 {
    501     if (fFILE == NULL)
    502         return false;
    503 
    504     if (sk_fwrite(buffer, size, fFILE) != size)
    505     {
    506         SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
    507         sk_fclose(fFILE);
    508         fFILE = NULL;
    509         return false;
    510     }
    511     return true;
    512 }
    513 
    514 void SkFILEWStream::flush()
    515 {
    516     if (fFILE)
    517         sk_fflush(fFILE);
    518 }
    519 
    520 ////////////////////////////////////////////////////////////////////////
    521 
    522 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
    523     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
    524 {
    525 }
    526 
    527 bool SkMemoryWStream::write(const void* buffer, size_t size)
    528 {
    529     size = SkMin32(size, fMaxLength - fBytesWritten);
    530     if (size > 0)
    531     {
    532         memcpy(fBuffer + fBytesWritten, buffer, size);
    533         fBytesWritten += size;
    534         return true;
    535     }
    536     return false;
    537 }
    538 
    539 ////////////////////////////////////////////////////////////////////////
    540 
    541 #define SkDynamicMemoryWStream_MinBlockSize   256
    542 
    543 struct SkDynamicMemoryWStream::Block {
    544     Block*  fNext;
    545     char*   fCurr;
    546     char*   fStop;
    547 
    548     const char* start() const { return (const char*)(this + 1); }
    549     char*   start() { return (char*)(this + 1); }
    550     size_t  avail() const { return fStop - fCurr; }
    551     size_t  written() const { return fCurr - this->start(); }
    552 
    553     void init(size_t size)
    554     {
    555         fNext = NULL;
    556         fCurr = this->start();
    557         fStop = this->start() + size;
    558     }
    559 
    560     const void* append(const void* data, size_t size)
    561     {
    562         SkASSERT((size_t)(fStop - fCurr) >= size);
    563         memcpy(fCurr, data, size);
    564         fCurr += size;
    565         return (const void*)((const char*)data + size);
    566     }
    567 };
    568 
    569 SkDynamicMemoryWStream::SkDynamicMemoryWStream() : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopyToCache(NULL)
    570 {
    571 }
    572 
    573 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
    574 {
    575     reset();
    576 }
    577 
    578 const char* SkDynamicMemoryWStream::detach()
    579 {
    580     const char* result = getStream();
    581     fCopyToCache = NULL;
    582     return result;
    583 }
    584 
    585 void SkDynamicMemoryWStream::reset()
    586 {
    587     sk_free(fCopyToCache);
    588     Block*  block = fHead;
    589 
    590     while (block != NULL) {
    591         Block*  next = block->fNext;
    592         sk_free(block);
    593         block = next;
    594     }
    595     fHead = fTail = NULL;
    596     fBytesWritten = 0;
    597     fCopyToCache = NULL;
    598 }
    599 
    600 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
    601 {
    602     if (count > 0) {
    603 
    604         if (fCopyToCache) {
    605             sk_free(fCopyToCache);
    606             fCopyToCache = NULL;
    607         }
    608         fBytesWritten += count;
    609 
    610         size_t  size;
    611 
    612         if (fTail != NULL && fTail->avail() > 0) {
    613             size = SkMin32(fTail->avail(), count);
    614             buffer = fTail->append(buffer, size);
    615             SkASSERT(count >= size);
    616             count -= size;
    617             if (count == 0)
    618                 return true;
    619         }
    620 
    621         size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
    622         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
    623         block->init(size);
    624         block->append(buffer, count);
    625 
    626         if (fTail != NULL)
    627             fTail->fNext = block;
    628         else
    629             fHead = fTail = block;
    630         fTail = block;
    631     }
    632     return true;
    633 }
    634 
    635 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
    636 {
    637     if (offset + count > fBytesWritten)
    638         return false; // test does not partially modify
    639     Block* block = fHead;
    640     while (block != NULL) {
    641         size_t size = block->written();
    642         if (offset < size) {
    643             size_t part = offset + count > size ? size - offset : count;
    644             memcpy(block->start() + offset, buffer, part);
    645             if (count <= part)
    646                 return true;
    647             count -= part;
    648             buffer = (const void*) ((char* ) buffer + part);
    649         }
    650         offset = offset > size ? offset - size : 0;
    651         block = block->fNext;
    652     }
    653     return false;
    654 }
    655 
    656 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
    657 {
    658     if (offset + count > fBytesWritten)
    659         return false; // test does not partially modify
    660     Block* block = fHead;
    661     while (block != NULL) {
    662         size_t size = block->written();
    663         if (offset < size) {
    664             size_t part = offset + count > size ? size - offset : count;
    665             memcpy(buffer, block->start() + offset, part);
    666             if (count <= part)
    667                 return true;
    668             count -= part;
    669             buffer = (void*) ((char* ) buffer + part);
    670         }
    671         offset = offset > size ? offset - size : 0;
    672         block = block->fNext;
    673     }
    674     return false;
    675 }
    676 
    677 void SkDynamicMemoryWStream::copyTo(void* dst) const
    678 {
    679     Block* block = fHead;
    680 
    681     while (block != NULL) {
    682         size_t size = block->written();
    683         memcpy(dst, block->start(), size);
    684         dst = (void*)((char*)dst + size);
    685         block = block->fNext;
    686     }
    687 }
    688 
    689 const char* SkDynamicMemoryWStream::getStream() const
    690 {
    691     if (fCopyToCache == NULL) {
    692         fCopyToCache = (char*)sk_malloc_throw(fBytesWritten);
    693         this->copyTo(fCopyToCache);
    694     }
    695     return fCopyToCache;
    696 }
    697 
    698 void SkDynamicMemoryWStream::padToAlign4()
    699 {
    700     // cast to remove unary-minus warning
    701     int padBytes = -(int)fBytesWritten & 0x03;
    702     if (padBytes == 0)
    703         return;
    704     int zero = 0;
    705     write(&zero, padBytes);
    706 }
    707 
    708 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    709 
    710 void SkDebugWStream::newline()
    711 {
    712 #ifdef SK_DEBUG
    713     SkDebugf("\n");
    714 #endif
    715 }
    716 
    717 bool SkDebugWStream::write(const void* buffer, size_t size)
    718 {
    719 #ifdef SK_DEBUG
    720     char* s = new char[size+1];
    721     memcpy(s, buffer, size);
    722     s[size] = 0;
    723     SkDebugf("%s", s);
    724     delete[] s;
    725 #endif
    726     return true;
    727 }
    728 
    729