Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      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 
      9 
     10 #include "SkStream.h"
     11 #include "SkData.h"
     12 #include "SkFixed.h"
     13 #include "SkString.h"
     14 #include "SkOSFile.h"
     15 
     16 ///////////////////////////////////////////////////////////////////////////////
     17 
     18 
     19 int8_t SkStream::readS8() {
     20     int8_t value;
     21     SkDEBUGCODE(size_t len =) this->read(&value, 1);
     22     SkASSERT(1 == len);
     23     return value;
     24 }
     25 
     26 int16_t SkStream::readS16() {
     27     int16_t value;
     28     SkDEBUGCODE(size_t len =) this->read(&value, 2);
     29     SkASSERT(2 == len);
     30     return value;
     31 }
     32 
     33 int32_t SkStream::readS32() {
     34     int32_t value;
     35     SkDEBUGCODE(size_t len =) this->read(&value, 4);
     36     SkASSERT(4 == len);
     37     return value;
     38 }
     39 
     40 SkScalar SkStream::readScalar() {
     41     SkScalar value;
     42     SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
     43     SkASSERT(sizeof(SkScalar) == len);
     44     return value;
     45 }
     46 
     47 #define SK_MAX_BYTE_FOR_U8          0xFD
     48 #define SK_BYTE_SENTINEL_FOR_U16    0xFE
     49 #define SK_BYTE_SENTINEL_FOR_U32    0xFF
     50 
     51 size_t SkStream::readPackedUInt() {
     52     uint8_t byte;
     53     if (!this->read(&byte, 1)) {
     54         return 0;
     55     }
     56     if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
     57         return this->readU16();
     58     } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
     59         return this->readU32();
     60     } else {
     61         return byte;
     62     }
     63 }
     64 
     65 SkData* SkStream::readData() {
     66     size_t size = this->readU32();
     67     if (0 == size) {
     68         return SkData::NewEmpty();
     69     } else {
     70         void* buffer = sk_malloc_throw(size);
     71         this->read(buffer, size);
     72         return SkData::NewFromMalloc(buffer, size);
     73     }
     74 }
     75 
     76 //////////////////////////////////////////////////////////////////////////////////////
     77 
     78 SkWStream::~SkWStream()
     79 {
     80 }
     81 
     82 void SkWStream::newline()
     83 {
     84     this->write("\n", 1);
     85 }
     86 
     87 void SkWStream::flush()
     88 {
     89 }
     90 
     91 bool SkWStream::writeText(const char text[])
     92 {
     93     SkASSERT(text);
     94     return this->write(text, strlen(text));
     95 }
     96 
     97 bool SkWStream::writeDecAsText(int32_t dec)
     98 {
     99     SkString    tmp;
    100     tmp.appendS32(dec);
    101     return this->write(tmp.c_str(), tmp.size());
    102 }
    103 
    104 bool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
    105 {
    106     SkString    tmp;
    107     tmp.appendS64(dec, minDigits);
    108     return this->write(tmp.c_str(), tmp.size());
    109 }
    110 
    111 bool SkWStream::writeHexAsText(uint32_t hex, int digits)
    112 {
    113     SkString    tmp;
    114     tmp.appendHex(hex, digits);
    115     return this->write(tmp.c_str(), tmp.size());
    116 }
    117 
    118 bool SkWStream::writeScalarAsText(SkScalar value)
    119 {
    120     SkString    tmp;
    121     tmp.appendScalar(value);
    122     return this->write(tmp.c_str(), tmp.size());
    123 }
    124 
    125 bool SkWStream::write8(U8CPU value) {
    126     uint8_t v = SkToU8(value);
    127     return this->write(&v, 1);
    128 }
    129 
    130 bool SkWStream::write16(U16CPU value) {
    131     uint16_t v = SkToU16(value);
    132     return this->write(&v, 2);
    133 }
    134 
    135 bool SkWStream::write32(uint32_t value) {
    136     return this->write(&value, 4);
    137 }
    138 
    139 bool SkWStream::writeScalar(SkScalar value) {
    140     return this->write(&value, sizeof(value));
    141 }
    142 
    143 int SkWStream::SizeOfPackedUInt(size_t value) {
    144     if (value <= SK_MAX_BYTE_FOR_U8) {
    145         return 1;
    146     } else if (value <= 0xFFFF) {
    147         return 3;
    148     }
    149     return 5;
    150 }
    151 
    152 bool SkWStream::writePackedUInt(size_t value) {
    153     uint8_t data[5];
    154     size_t len = 1;
    155     if (value <= SK_MAX_BYTE_FOR_U8) {
    156         data[0] = value;
    157         len = 1;
    158     } else if (value <= 0xFFFF) {
    159         uint16_t value16 = value;
    160         data[0] = SK_BYTE_SENTINEL_FOR_U16;
    161         memcpy(&data[1], &value16, 2);
    162         len = 3;
    163     } else {
    164         uint32_t value32 = SkToU32(value);
    165         data[0] = SK_BYTE_SENTINEL_FOR_U32;
    166         memcpy(&data[1], &value32, 4);
    167         len = 5;
    168     }
    169     return this->write(data, len);
    170 }
    171 
    172 bool SkWStream::writeStream(SkStream* stream, size_t length) {
    173     char scratch[1024];
    174     const size_t MAX = sizeof(scratch);
    175 
    176     while (length != 0) {
    177         size_t n = length;
    178         if (n > MAX) {
    179             n = MAX;
    180         }
    181         stream->read(scratch, n);
    182         if (!this->write(scratch, n)) {
    183             return false;
    184         }
    185         length -= n;
    186     }
    187     return true;
    188 }
    189 
    190 bool SkWStream::writeData(const SkData* data) {
    191     if (data) {
    192         this->write32(SkToU32(data->size()));
    193         this->write(data->data(), data->size());
    194     } else {
    195         this->write32(0);
    196     }
    197     return true;
    198 }
    199 
    200 ///////////////////////////////////////////////////////////////////////////////
    201 
    202 SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
    203     fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
    204 }
    205 
    206 SkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
    207     : fFILE((SkFILE*)file)
    208     , fOwnership(ownership) {
    209 }
    210 
    211 SkFILEStream::~SkFILEStream() {
    212     if (fFILE && fOwnership != kCallerRetains_Ownership) {
    213         sk_fclose(fFILE);
    214     }
    215 }
    216 
    217 void SkFILEStream::setPath(const char path[]) {
    218     fName.set(path);
    219     if (fFILE) {
    220         sk_fclose(fFILE);
    221         fFILE = NULL;
    222     }
    223     if (path) {
    224         fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
    225     }
    226 }
    227 
    228 size_t SkFILEStream::read(void* buffer, size_t size) {
    229     if (fFILE) {
    230         return sk_fread(buffer, size, fFILE);
    231     }
    232     return 0;
    233 }
    234 
    235 bool SkFILEStream::isAtEnd() const {
    236     return sk_feof(fFILE);
    237 }
    238 
    239 bool SkFILEStream::rewind() {
    240     if (fFILE) {
    241         if (sk_frewind(fFILE)) {
    242             return true;
    243         }
    244         // we hit an error
    245         sk_fclose(fFILE);
    246         fFILE = NULL;
    247     }
    248     return false;
    249 }
    250 
    251 SkStreamAsset* SkFILEStream::duplicate() const {
    252     if (NULL == fFILE) {
    253         return new SkMemoryStream();
    254     }
    255 
    256     if (NULL != fData.get()) {
    257         return new SkMemoryStream(fData);
    258     }
    259 
    260     if (!fName.isEmpty()) {
    261         SkAutoTUnref<SkFILEStream> that(new SkFILEStream(fName.c_str()));
    262         if (sk_fidentical(that->fFILE, this->fFILE)) {
    263             return that.detach();
    264         }
    265     }
    266 
    267     fData.reset(SkData::NewFromFILE(fFILE));
    268     if (NULL == fData.get()) {
    269         return NULL;
    270     }
    271     return new SkMemoryStream(fData);
    272 }
    273 
    274 size_t SkFILEStream::getPosition() const {
    275     return sk_ftell(fFILE);
    276 }
    277 
    278 bool SkFILEStream::seek(size_t position) {
    279     return sk_fseek(fFILE, position);
    280 }
    281 
    282 bool SkFILEStream::move(long offset) {
    283     return sk_fmove(fFILE, offset);
    284 }
    285 
    286 SkStreamAsset* SkFILEStream::fork() const {
    287     SkAutoTUnref<SkStreamAsset> that(this->duplicate());
    288     that->seek(this->getPosition());
    289     return that.detach();
    290 }
    291 
    292 size_t SkFILEStream::getLength() const {
    293     return sk_fgetsize(fFILE);
    294 }
    295 
    296 const void* SkFILEStream::getMemoryBase() {
    297     if (NULL == fData.get()) {
    298         return NULL;
    299     }
    300     return fData->data();
    301 }
    302 
    303 ///////////////////////////////////////////////////////////////////////////////
    304 
    305 static SkData* newFromParams(const void* src, size_t size, bool copyData) {
    306     if (copyData) {
    307         return SkData::NewWithCopy(src, size);
    308     } else {
    309         return SkData::NewWithProc(src, size, NULL, NULL);
    310     }
    311 }
    312 
    313 SkMemoryStream::SkMemoryStream() {
    314     fData = SkData::NewEmpty();
    315     fOffset = 0;
    316 }
    317 
    318 SkMemoryStream::SkMemoryStream(size_t size) {
    319     fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
    320     fOffset = 0;
    321 }
    322 
    323 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
    324     fData = newFromParams(src, size, copyData);
    325     fOffset = 0;
    326 }
    327 
    328 SkMemoryStream::SkMemoryStream(SkData* data) {
    329     if (NULL == data) {
    330         fData = SkData::NewEmpty();
    331     } else {
    332         fData = data;
    333         fData->ref();
    334     }
    335     fOffset = 0;
    336 }
    337 
    338 SkMemoryStream::~SkMemoryStream() {
    339     fData->unref();
    340 }
    341 
    342 void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
    343     fData->unref();
    344     fData = SkData::NewFromMalloc(src, size);
    345     fOffset = 0;
    346 }
    347 
    348 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
    349     fData->unref();
    350     fData = newFromParams(src, size, copyData);
    351     fOffset = 0;
    352 }
    353 
    354 SkData* SkMemoryStream::copyToData() const {
    355     fData->ref();
    356     return fData;
    357 }
    358 
    359 SkData* SkMemoryStream::setData(SkData* data) {
    360     fData->unref();
    361     if (NULL == data) {
    362         fData = SkData::NewEmpty();
    363     } else {
    364         fData = data;
    365         fData->ref();
    366     }
    367     fOffset = 0;
    368     return data;
    369 }
    370 
    371 void SkMemoryStream::skipToAlign4() {
    372     // cast to remove unary-minus warning
    373     fOffset += -(int)fOffset & 0x03;
    374 }
    375 
    376 size_t SkMemoryStream::read(void* buffer, size_t size) {
    377     size_t dataSize = fData->size();
    378 
    379     if (size > dataSize - fOffset) {
    380         size = dataSize - fOffset;
    381     }
    382     if (buffer) {
    383         memcpy(buffer, fData->bytes() + fOffset, size);
    384     }
    385     fOffset += size;
    386     return size;
    387 }
    388 
    389 bool SkMemoryStream::isAtEnd() const {
    390     return fOffset == fData->size();
    391 }
    392 
    393 bool SkMemoryStream::rewind() {
    394     fOffset = 0;
    395     return true;
    396 }
    397 
    398 SkMemoryStream* SkMemoryStream::duplicate() const {
    399     return SkNEW_ARGS(SkMemoryStream, (fData));
    400 }
    401 
    402 size_t SkMemoryStream::getPosition() const {
    403     return fOffset;
    404 }
    405 
    406 bool SkMemoryStream::seek(size_t position) {
    407     fOffset = position > fData->size()
    408             ? fData->size()
    409             : position;
    410     return true;
    411 }
    412 
    413 bool SkMemoryStream::move(long offset) {
    414     return this->seek(fOffset + offset);
    415 }
    416 
    417 SkMemoryStream* SkMemoryStream::fork() const {
    418     SkAutoTUnref<SkMemoryStream> that(this->duplicate());
    419     that->seek(fOffset);
    420     return that.detach();
    421 }
    422 
    423 size_t SkMemoryStream::getLength() const {
    424     return fData->size();
    425 }
    426 
    427 const void* SkMemoryStream::getMemoryBase() {
    428     return fData->data();
    429 }
    430 
    431 const void* SkMemoryStream::getAtPos() {
    432     return fData->bytes() + fOffset;
    433 }
    434 
    435 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    436 /////////////////////////////////////////////////////////////////////////////////////////////////////////
    437 
    438 SkFILEWStream::SkFILEWStream(const char path[])
    439 {
    440     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
    441 }
    442 
    443 SkFILEWStream::~SkFILEWStream()
    444 {
    445     if (fFILE) {
    446         sk_fclose(fFILE);
    447     }
    448 }
    449 
    450 size_t SkFILEWStream::bytesWritten() const {
    451     return sk_ftell(fFILE);
    452 }
    453 
    454 bool SkFILEWStream::write(const void* buffer, size_t size)
    455 {
    456     if (fFILE == NULL) {
    457         return false;
    458     }
    459 
    460     if (sk_fwrite(buffer, size, fFILE) != size)
    461     {
    462         SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
    463         sk_fclose(fFILE);
    464         fFILE = NULL;
    465         return false;
    466     }
    467     return true;
    468 }
    469 
    470 void SkFILEWStream::flush()
    471 {
    472     if (fFILE) {
    473         sk_fflush(fFILE);
    474     }
    475 }
    476 
    477 ////////////////////////////////////////////////////////////////////////
    478 
    479 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
    480     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
    481 {
    482 }
    483 
    484 bool SkMemoryWStream::write(const void* buffer, size_t size) {
    485     size = SkTMin(size, fMaxLength - fBytesWritten);
    486     if (size > 0) {
    487         memcpy(fBuffer + fBytesWritten, buffer, size);
    488         fBytesWritten += size;
    489         return true;
    490     }
    491     return false;
    492 }
    493 
    494 ////////////////////////////////////////////////////////////////////////
    495 
    496 #define SkDynamicMemoryWStream_MinBlockSize   256
    497 
    498 struct SkDynamicMemoryWStream::Block {
    499     Block*  fNext;
    500     char*   fCurr;
    501     char*   fStop;
    502 
    503     const char* start() const { return (const char*)(this + 1); }
    504     char*   start() { return (char*)(this + 1); }
    505     size_t  avail() const { return fStop - fCurr; }
    506     size_t  written() const { return fCurr - this->start(); }
    507 
    508     void init(size_t size)
    509     {
    510         fNext = NULL;
    511         fCurr = this->start();
    512         fStop = this->start() + size;
    513     }
    514 
    515     const void* append(const void* data, size_t size)
    516     {
    517         SkASSERT((size_t)(fStop - fCurr) >= size);
    518         memcpy(fCurr, data, size);
    519         fCurr += size;
    520         return (const void*)((const char*)data + size);
    521     }
    522 };
    523 
    524 SkDynamicMemoryWStream::SkDynamicMemoryWStream()
    525     : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
    526 {
    527 }
    528 
    529 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
    530 {
    531     reset();
    532 }
    533 
    534 void SkDynamicMemoryWStream::reset()
    535 {
    536     this->invalidateCopy();
    537 
    538     Block*  block = fHead;
    539 
    540     while (block != NULL) {
    541         Block*  next = block->fNext;
    542         sk_free(block);
    543         block = next;
    544     }
    545     fHead = fTail = NULL;
    546     fBytesWritten = 0;
    547 }
    548 
    549 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
    550 {
    551     if (count > 0) {
    552         this->invalidateCopy();
    553 
    554         fBytesWritten += count;
    555 
    556         size_t  size;
    557 
    558         if (fTail != NULL && fTail->avail() > 0) {
    559             size = SkTMin(fTail->avail(), count);
    560             buffer = fTail->append(buffer, size);
    561             SkASSERT(count >= size);
    562             count -= size;
    563             if (count == 0)
    564                 return true;
    565         }
    566 
    567         size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize);
    568         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
    569         block->init(size);
    570         block->append(buffer, count);
    571 
    572         if (fTail != NULL)
    573             fTail->fNext = block;
    574         else
    575             fHead = fTail = block;
    576         fTail = block;
    577     }
    578     return true;
    579 }
    580 
    581 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
    582 {
    583     if (offset + count > fBytesWritten) {
    584         return false; // test does not partially modify
    585     }
    586 
    587     this->invalidateCopy();
    588 
    589     Block* block = fHead;
    590     while (block != NULL) {
    591         size_t size = block->written();
    592         if (offset < size) {
    593             size_t part = offset + count > size ? size - offset : count;
    594             memcpy(block->start() + offset, buffer, part);
    595             if (count <= part)
    596                 return true;
    597             count -= part;
    598             buffer = (const void*) ((char* ) buffer + part);
    599         }
    600         offset = offset > size ? offset - size : 0;
    601         block = block->fNext;
    602     }
    603     return false;
    604 }
    605 
    606 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
    607 {
    608     if (offset + count > fBytesWritten)
    609         return false; // test does not partially modify
    610     Block* block = fHead;
    611     while (block != NULL) {
    612         size_t size = block->written();
    613         if (offset < size) {
    614             size_t part = offset + count > size ? size - offset : count;
    615             memcpy(buffer, block->start() + offset, part);
    616             if (count <= part)
    617                 return true;
    618             count -= part;
    619             buffer = (void*) ((char* ) buffer + part);
    620         }
    621         offset = offset > size ? offset - size : 0;
    622         block = block->fNext;
    623     }
    624     return false;
    625 }
    626 
    627 void SkDynamicMemoryWStream::copyTo(void* dst) const
    628 {
    629     if (fCopy) {
    630         memcpy(dst, fCopy->data(), fBytesWritten);
    631     } else {
    632         Block* block = fHead;
    633 
    634         while (block != NULL) {
    635             size_t size = block->written();
    636             memcpy(dst, block->start(), size);
    637             dst = (void*)((char*)dst + size);
    638             block = block->fNext;
    639         }
    640     }
    641 }
    642 
    643 void SkDynamicMemoryWStream::padToAlign4()
    644 {
    645     // cast to remove unary-minus warning
    646     int padBytes = -(int)fBytesWritten & 0x03;
    647     if (padBytes == 0)
    648         return;
    649     int zero = 0;
    650     write(&zero, padBytes);
    651 }
    652 
    653 SkData* SkDynamicMemoryWStream::copyToData() const {
    654     if (NULL == fCopy) {
    655         void* buffer = sk_malloc_throw(fBytesWritten);
    656         this->copyTo(buffer);
    657         fCopy = SkData::NewFromMalloc(buffer, fBytesWritten);
    658     }
    659     fCopy->ref();
    660     return fCopy;
    661 }
    662 
    663 void SkDynamicMemoryWStream::invalidateCopy() {
    664     if (fCopy) {
    665         fCopy->unref();
    666         fCopy = NULL;
    667     }
    668 }
    669 
    670 class SkBlockMemoryRefCnt : public SkRefCnt {
    671 public:
    672     explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
    673 
    674     virtual ~SkBlockMemoryRefCnt() {
    675         SkDynamicMemoryWStream::Block* block = fHead;
    676         while (block != NULL) {
    677             SkDynamicMemoryWStream::Block* next = block->fNext;
    678             sk_free(block);
    679             block = next;
    680         }
    681     }
    682 
    683     SkDynamicMemoryWStream::Block* const fHead;
    684 };
    685 
    686 class SkBlockMemoryStream : public SkStreamAsset {
    687 public:
    688     SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
    689         : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
    690         , fSize(size) , fOffset(0), fCurrentOffset(0) { }
    691 
    692     SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
    693         : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
    694         , fSize(size) , fOffset(0), fCurrentOffset(0) { }
    695 
    696     virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE {
    697         size_t count = rawCount;
    698         if (fOffset + count > fSize) {
    699             count = fSize - fOffset;
    700         }
    701         size_t bytesLeftToRead = count;
    702         while (fCurrent != NULL) {
    703             size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
    704             size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
    705             if (buffer) {
    706                 memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
    707                 buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
    708             }
    709             if (bytesLeftToRead <= bytesFromCurrent) {
    710                 fCurrentOffset += bytesFromCurrent;
    711                 fOffset += count;
    712                 return count;
    713             }
    714             bytesLeftToRead -= bytesFromCurrent;
    715             fCurrent = fCurrent->fNext;
    716             fCurrentOffset = 0;
    717         }
    718         SkASSERT(false);
    719         return 0;
    720     }
    721 
    722     virtual bool isAtEnd() const SK_OVERRIDE {
    723         return fOffset == fSize;
    724     }
    725 
    726     virtual bool rewind() SK_OVERRIDE {
    727         fCurrent = fBlockMemory->fHead;
    728         fOffset = 0;
    729         fCurrentOffset = 0;
    730         return true;
    731     }
    732 
    733     virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE {
    734         return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
    735     }
    736 
    737     virtual size_t getPosition() const SK_OVERRIDE {
    738         return fOffset;
    739     }
    740 
    741     virtual bool seek(size_t position) SK_OVERRIDE {
    742         // If possible, skip forward.
    743         if (position >= fOffset) {
    744             size_t skipAmount = position - fOffset;
    745             return this->skip(skipAmount) == skipAmount;
    746         }
    747         // If possible, move backward within the current block.
    748         size_t moveBackAmount = fOffset - position;
    749         if (moveBackAmount <= fCurrentOffset) {
    750             fCurrentOffset -= moveBackAmount;
    751             fOffset -= moveBackAmount;
    752             return true;
    753         }
    754         // Otherwise rewind and move forward.
    755         return this->rewind() && this->skip(position) == position;
    756     }
    757 
    758     virtual bool move(long offset) SK_OVERRIDE {
    759         return seek(fOffset + offset);
    760     }
    761 
    762     virtual SkBlockMemoryStream* fork() const SK_OVERRIDE {
    763         SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate());
    764         that->fCurrent = this->fCurrent;
    765         that->fOffset = this->fOffset;
    766         that->fCurrentOffset = this->fCurrentOffset;
    767         return that.detach();
    768     }
    769 
    770     virtual size_t getLength() const SK_OVERRIDE {
    771         return fSize;
    772     }
    773 
    774     virtual const void* getMemoryBase() SK_OVERRIDE {
    775         if (NULL == fBlockMemory->fHead->fNext) {
    776             return fBlockMemory->fHead->start();
    777         }
    778         return NULL;
    779     }
    780 
    781 private:
    782     SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
    783     SkDynamicMemoryWStream::Block const * fCurrent;
    784     size_t const fSize;
    785     size_t fOffset;
    786     size_t fCurrentOffset;
    787 };
    788 
    789 SkStreamAsset* SkDynamicMemoryWStream::detachAsStream() {
    790     if (fCopy) {
    791         SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy));
    792         this->reset();
    793         return stream;
    794     }
    795     SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten));
    796     fHead = 0;
    797     this->reset();
    798     return stream;
    799 }
    800 
    801 ///////////////////////////////////////////////////////////////////////////////
    802 
    803 void SkDebugWStream::newline()
    804 {
    805 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
    806     SkDebugf("\n");
    807     fBytesWritten++;
    808 #endif
    809 }
    810 
    811 bool SkDebugWStream::write(const void* buffer, size_t size)
    812 {
    813 #if defined(SK_DEBUG) || defined(SK_DEVELOPER)
    814     char* s = new char[size+1];
    815     memcpy(s, buffer, size);
    816     s[size] = 0;
    817     SkDebugf("%s", s);
    818     delete[] s;
    819     fBytesWritten += size;
    820 #endif
    821     return true;
    822 }
    823 
    824 ///////////////////////////////////////////////////////////////////////////////
    825 ///////////////////////////////////////////////////////////////////////////////
    826 
    827 
    828 static SkData* mmap_filename(const char path[]) {
    829     SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
    830     if (NULL == file) {
    831         return NULL;
    832     }
    833 
    834     SkData* data = SkData::NewFromFILE(file);
    835     sk_fclose(file);
    836     return data;
    837 }
    838 
    839 SkStreamAsset* SkStream::NewFromFile(const char path[]) {
    840     SkAutoTUnref<SkData> data(mmap_filename(path));
    841     if (data.get()) {
    842         return SkNEW_ARGS(SkMemoryStream, (data.get()));
    843     }
    844 
    845     // If we get here, then our attempt at using mmap failed, so try normal
    846     // file access.
    847     SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path));
    848     if (!stream->isValid()) {
    849         stream->unref();
    850         stream = NULL;
    851     }
    852     return stream;
    853 }
    854