1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h"
118d0b5770f8fcfdeb8ad9808e58c49116f14b6190reed@google.com#include "SkData.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFixed.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkString.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkOSFile.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
163b429984664e88e0530eb6a1461a828898d8d96breed@google.com///////////////////////////////////////////////////////////////////////////////
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint8_t SkStream::readS8() {
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int8_t value;
2104225dcdec5a01bc9889b7fb03e7aceb87fccc6ereed@android.com    SkDEBUGCODE(size_t len =) this->read(&value, 1);
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(1 == len);
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return value;
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint16_t SkStream::readS16() {
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int16_t value;
2804225dcdec5a01bc9889b7fb03e7aceb87fccc6ereed@android.com    SkDEBUGCODE(size_t len =) this->read(&value, 2);
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(2 == len);
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return value;
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint32_t SkStream::readS32() {
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int32_t value;
3504225dcdec5a01bc9889b7fb03e7aceb87fccc6ereed@android.com    SkDEBUGCODE(size_t len =) this->read(&value, 4);
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(4 == len);
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return value;
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScalar SkStream::readScalar() {
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar value;
4204225dcdec5a01bc9889b7fb03e7aceb87fccc6ereed@android.com    SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(sizeof(SkScalar) == len);
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return value;
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4719f286b6f4ca4c124250caeea7f427c870c64370reed@google.com#define SK_MAX_BYTE_FOR_U8          0xFD
4819f286b6f4ca4c124250caeea7f427c870c64370reed@google.com#define SK_BYTE_SENTINEL_FOR_U16    0xFE
4919f286b6f4ca4c124250caeea7f427c870c64370reed@google.com#define SK_BYTE_SENTINEL_FOR_U32    0xFF
5019f286b6f4ca4c124250caeea7f427c870c64370reed@google.com
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comsize_t SkStream::readPackedUInt() {
52fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint8_t byte;
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!this->read(&byte, 1)) {
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5619f286b6f4ca4c124250caeea7f427c870c64370reed@google.com    if (SK_BYTE_SENTINEL_FOR_U16 == byte) {
5719f286b6f4ca4c124250caeea7f427c870c64370reed@google.com        return this->readU16();
5819f286b6f4ca4c124250caeea7f427c870c64370reed@google.com    } else if (SK_BYTE_SENTINEL_FOR_U32 == byte) {
5919f286b6f4ca4c124250caeea7f427c870c64370reed@google.com        return this->readU32();
6019f286b6f4ca4c124250caeea7f427c870c64370reed@google.com    } else {
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return byte;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
650985c558fc7e014f5680a7532270c6cbad2bca6areed@google.comSkData* SkStream::readData() {
662e07942f42937b87f82a16e11b1bb26acd09896ereed@google.com    size_t size = this->readU32();
672e07942f42937b87f82a16e11b1bb26acd09896ereed@google.com    if (0 == size) {
682e07942f42937b87f82a16e11b1bb26acd09896ereed@google.com        return SkData::NewEmpty();
692e07942f42937b87f82a16e11b1bb26acd09896ereed@google.com    } else {
702e07942f42937b87f82a16e11b1bb26acd09896ereed@google.com        void* buffer = sk_malloc_throw(size);
710985c558fc7e014f5680a7532270c6cbad2bca6areed@google.com        this->read(buffer, size);
722e07942f42937b87f82a16e11b1bb26acd09896ereed@google.com        return SkData::NewFromMalloc(buffer, size);
732e07942f42937b87f82a16e11b1bb26acd09896ereed@google.com    }
742e07942f42937b87f82a16e11b1bb26acd09896ereed@google.com}
752e07942f42937b87f82a16e11b1bb26acd09896ereed@google.com
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkWStream::~SkWStream()
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkWStream::newline()
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->write("\n", 1);
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkWStream::flush()
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkWStream::writeText(const char text[])
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text);
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->write(text, strlen(text));
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkWStream::writeDecAsText(int32_t dec)
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkString    tmp;
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    tmp.appendS32(dec);
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->write(tmp.c_str(), tmp.size());
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
104d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.orgbool SkWStream::writeBigDecAsText(int64_t dec, int minDigits)
105d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org{
106d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    SkString    tmp;
107d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    tmp.appendS64(dec, minDigits);
108d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    return this->write(tmp.c_str(), tmp.size());
109d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org}
110d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkWStream::writeHexAsText(uint32_t hex, int digits)
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkString    tmp;
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    tmp.appendHex(hex, digits);
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->write(tmp.c_str(), tmp.size());
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkWStream::writeScalarAsText(SkScalar value)
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkString    tmp;
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    tmp.appendScalar(value);
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->write(tmp.c_str(), tmp.size());
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkWStream::write8(U8CPU value) {
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint8_t v = SkToU8(value);
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->write(&v, 1);
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkWStream::write16(U16CPU value) {
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t v = SkToU16(value);
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->write(&v, 2);
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkWStream::write32(uint32_t value) {
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->write(&value, 4);
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkWStream::writeScalar(SkScalar value) {
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->write(&value, sizeof(value));
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
143dcb8e54ffdc9194744c0ec839969102bd0f582c6commit-bot@chromium.orgint SkWStream::SizeOfPackedUInt(size_t value) {
144dcb8e54ffdc9194744c0ec839969102bd0f582c6commit-bot@chromium.org    if (value <= SK_MAX_BYTE_FOR_U8) {
145dcb8e54ffdc9194744c0ec839969102bd0f582c6commit-bot@chromium.org        return 1;
146dcb8e54ffdc9194744c0ec839969102bd0f582c6commit-bot@chromium.org    } else if (value <= 0xFFFF) {
147dcb8e54ffdc9194744c0ec839969102bd0f582c6commit-bot@chromium.org        return 3;
148dcb8e54ffdc9194744c0ec839969102bd0f582c6commit-bot@chromium.org    }
149dcb8e54ffdc9194744c0ec839969102bd0f582c6commit-bot@chromium.org    return 5;
150dcb8e54ffdc9194744c0ec839969102bd0f582c6commit-bot@chromium.org}
151dcb8e54ffdc9194744c0ec839969102bd0f582c6commit-bot@chromium.org
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkWStream::writePackedUInt(size_t value) {
15319f286b6f4ca4c124250caeea7f427c870c64370reed@google.com    uint8_t data[5];
15419f286b6f4ca4c124250caeea7f427c870c64370reed@google.com    size_t len = 1;
15519f286b6f4ca4c124250caeea7f427c870c64370reed@google.com    if (value <= SK_MAX_BYTE_FOR_U8) {
15619f286b6f4ca4c124250caeea7f427c870c64370reed@google.com        data[0] = value;
15719f286b6f4ca4c124250caeea7f427c870c64370reed@google.com        len = 1;
15819f286b6f4ca4c124250caeea7f427c870c64370reed@google.com    } else if (value <= 0xFFFF) {
15919f286b6f4ca4c124250caeea7f427c870c64370reed@google.com        uint16_t value16 = value;
16019f286b6f4ca4c124250caeea7f427c870c64370reed@google.com        data[0] = SK_BYTE_SENTINEL_FOR_U16;
16119f286b6f4ca4c124250caeea7f427c870c64370reed@google.com        memcpy(&data[1], &value16, 2);
16219f286b6f4ca4c124250caeea7f427c870c64370reed@google.com        len = 3;
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
164f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org        uint32_t value32 = SkToU32(value);
16519f286b6f4ca4c124250caeea7f427c870c64370reed@google.com        data[0] = SK_BYTE_SENTINEL_FOR_U32;
16619f286b6f4ca4c124250caeea7f427c870c64370reed@google.com        memcpy(&data[1], &value32, 4);
16719f286b6f4ca4c124250caeea7f427c870c64370reed@google.com        len = 5;
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16919f286b6f4ca4c124250caeea7f427c870c64370reed@google.com    return this->write(data, len);
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkWStream::writeStream(SkStream* stream, size_t length) {
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char scratch[1024];
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const size_t MAX = sizeof(scratch);
175fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (length != 0) {
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        size_t n = length;
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (n > MAX) {
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            n = MAX;
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        stream->read(scratch, n);
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!this->write(scratch, n)) {
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return false;
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        length -= n;
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1908a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.combool SkWStream::writeData(const SkData* data) {
1918a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    if (data) {
192f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org        this->write32(SkToU32(data->size()));
1938a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        this->write(data->data(), data->size());
1942e07942f42937b87f82a16e11b1bb26acd09896ereed@google.com    } else {
1952e07942f42937b87f82a16e11b1bb26acd09896ereed@google.com        this->write32(0);
1968a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    }
1978a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    return true;
1988a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com}
1998a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com
2008a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com///////////////////////////////////////////////////////////////////////////////
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2026cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comSkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) {
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2066cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comSkFILEStream::SkFILEStream(FILE* file, Ownership ownership)
2076cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    : fFILE((SkFILE*)file)
2086cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    , fOwnership(ownership) {
2096cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com}
2106cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
21154d5f83c33ad123aa398e1c3eaf8394d972d5d3fmike@reedtribe.orgSkFILEStream::~SkFILEStream() {
2126cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    if (fFILE && fOwnership != kCallerRetains_Ownership) {
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_fclose(fFILE);
21454d5f83c33ad123aa398e1c3eaf8394d972d5d3fmike@reedtribe.org    }
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21754d5f83c33ad123aa398e1c3eaf8394d972d5d3fmike@reedtribe.orgvoid SkFILEStream::setPath(const char path[]) {
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fName.set(path);
21954d5f83c33ad123aa398e1c3eaf8394d972d5d3fmike@reedtribe.org    if (fFILE) {
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_fclose(fFILE);
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFILE = NULL;
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22354d5f83c33ad123aa398e1c3eaf8394d972d5d3fmike@reedtribe.org    if (path) {
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
22554d5f83c33ad123aa398e1c3eaf8394d972d5d3fmike@reedtribe.org    }
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2286cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comsize_t SkFILEStream::read(void* buffer, size_t size) {
2296cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    if (fFILE) {
2306cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        return sk_fread(buffer, size, fFILE);
2316cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    }
2326cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return 0;
2336cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com}
2346cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
2356cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool SkFILEStream::isAtEnd() const {
2366cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return sk_feof(fFILE);
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23954d5f83c33ad123aa398e1c3eaf8394d972d5d3fmike@reedtribe.orgbool SkFILEStream::rewind() {
24054d5f83c33ad123aa398e1c3eaf8394d972d5d3fmike@reedtribe.org    if (fFILE) {
24154d5f83c33ad123aa398e1c3eaf8394d972d5d3fmike@reedtribe.org        if (sk_frewind(fFILE)) {
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
24354d5f83c33ad123aa398e1c3eaf8394d972d5d3fmike@reedtribe.org        }
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // we hit an error
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_fclose(fFILE);
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFILE = NULL;
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2516cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comSkStreamAsset* SkFILEStream::duplicate() const {
2526cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    if (NULL == fFILE) {
2536cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        return new SkMemoryStream();
2546cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    }
2556cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
2566cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    if (NULL != fData.get()) {
2576cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        return new SkMemoryStream(fData);
2586cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    }
2596cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
2606cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    if (!fName.isEmpty()) {
2616cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        SkAutoTUnref<SkFILEStream> that(new SkFILEStream(fName.c_str()));
2626cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        if (sk_fidentical(that->fFILE, this->fFILE)) {
2636cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com            return that.detach();
26454d5f83c33ad123aa398e1c3eaf8394d972d5d3fmike@reedtribe.org        }
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2666cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
2676cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    fData.reset(SkData::NewFromFILE(fFILE));
2686cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    if (NULL == fData.get()) {
2696cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        return NULL;
2706cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    }
2716cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return new SkMemoryStream(fData);
2726cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com}
2736cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
2746cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comsize_t SkFILEStream::getPosition() const {
2756cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return sk_ftell(fFILE);
2766cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com}
2776cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
2786cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool SkFILEStream::seek(size_t position) {
2796cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return sk_fseek(fFILE, position);
2806cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com}
2816cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
2826cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool SkFILEStream::move(long offset) {
2836cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return sk_fmove(fFILE, offset);
2846cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com}
2856cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
2866cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comSkStreamAsset* SkFILEStream::fork() const {
2876cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    SkAutoTUnref<SkStreamAsset> that(this->duplicate());
2886cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    that->seek(this->getPosition());
2896cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return that.detach();
2906cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com}
2916cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
2926cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comsize_t SkFILEStream::getLength() const {
2936cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return sk_fgetsize(fFILE);
2946cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com}
2956cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
2966cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comconst void* SkFILEStream::getMemoryBase() {
2976cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    if (NULL == fData.get()) {
2986cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        return NULL;
2996cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    }
3006cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return fData->data();
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3038a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com///////////////////////////////////////////////////////////////////////////////
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30567d0cff9acb2f2a9fe19c5282ca06ac3332a043creed@google.comstatic SkData* newFromParams(const void* src, size_t size, bool copyData) {
30667d0cff9acb2f2a9fe19c5282ca06ac3332a043creed@google.com    if (copyData) {
30767d0cff9acb2f2a9fe19c5282ca06ac3332a043creed@google.com        return SkData::NewWithCopy(src, size);
30867d0cff9acb2f2a9fe19c5282ca06ac3332a043creed@google.com    } else {
30967d0cff9acb2f2a9fe19c5282ca06ac3332a043creed@google.com        return SkData::NewWithProc(src, size, NULL, NULL);
31067d0cff9acb2f2a9fe19c5282ca06ac3332a043creed@google.com    }
31167d0cff9acb2f2a9fe19c5282ca06ac3332a043creed@google.com}
31267d0cff9acb2f2a9fe19c5282ca06ac3332a043creed@google.com
3138a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comSkMemoryStream::SkMemoryStream() {
3148a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    fData = SkData::NewEmpty();
3158a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    fOffset = 0;
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkMemoryStream::SkMemoryStream(size_t size) {
3198a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fOffset = 0;
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3238a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comSkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
32467d0cff9acb2f2a9fe19c5282ca06ac3332a043creed@google.com    fData = newFromParams(src, size, copyData);
3258a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    fOffset = 0;
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
328e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.comSkMemoryStream::SkMemoryStream(SkData* data) {
329e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com    if (NULL == data) {
330e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com        fData = SkData::NewEmpty();
331e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com    } else {
332e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com        fData = data;
333e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com        fData->ref();
334e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com    }
335c62b726dd1c839170466b23e8d0381c395526954robertphillips@google.com    fOffset = 0;
336f515ffc3d44975a09755276e572448061df3e2fehumper@google.com}
337f515ffc3d44975a09755276e572448061df3e2fehumper@google.com
3388a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comSkMemoryStream::~SkMemoryStream() {
3398a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    fData->unref();
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3428a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comvoid SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
3438a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    fData->unref();
3448a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    fData = SkData::NewFromMalloc(src, size);
34557f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    fOffset = 0;
34657f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com}
34757f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com
3488a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comvoid SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
3498a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    fData->unref();
35067d0cff9acb2f2a9fe19c5282ca06ac3332a043creed@google.com    fData = newFromParams(src, size, copyData);
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fOffset = 0;
3528a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com}
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3548a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comSkData* SkMemoryStream::copyToData() const {
3558a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    fData->ref();
3568a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    return fData;
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3598a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comSkData* SkMemoryStream::setData(SkData* data) {
360e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com    fData->unref();
361e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com    if (NULL == data) {
362e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com        fData = SkData::NewEmpty();
363e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com    } else {
364e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com        fData = data;
365e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com        fData->ref();
366e490420efc931db8d2c8f397ddf704aab980295dscroggo@google.com    }
36710822c6daabf836f73e468003787d11bf33aba66bungeman@google.com    fOffset = 0;
3688a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    return data;
3698a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com}
3708a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com
3718a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comvoid SkMemoryStream::skipToAlign4() {
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // cast to remove unary-minus warning
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fOffset += -(int)fOffset & 0x03;
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3768a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comsize_t SkMemoryStream::read(void* buffer, size_t size) {
3778a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    size_t dataSize = fData->size();
3788a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com
3798a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    if (size > dataSize - fOffset) {
3808a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        size = dataSize - fOffset;
3818a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    }
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (buffer) {
3838a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        memcpy(buffer, fData->bytes() + fOffset, size);
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fOffset += size;
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return size;
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3896cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool SkMemoryStream::isAtEnd() const {
3906cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return fOffset == fData->size();
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3936cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool SkMemoryStream::rewind() {
3946cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    fOffset = 0;
3956cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return true;
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3986cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comSkMemoryStream* SkMemoryStream::duplicate() const {
3996cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return SkNEW_ARGS(SkMemoryStream, (fData));
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4026cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comsize_t SkMemoryStream::getPosition() const {
4036cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return fOffset;
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4066cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool SkMemoryStream::seek(size_t position) {
4076cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    fOffset = position > fData->size()
4086cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com            ? fData->size()
4096cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com            : position;
4106cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return true;
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4136cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.combool SkMemoryStream::move(long offset) {
4146cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return this->seek(fOffset + offset);
4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4176cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comSkMemoryStream* SkMemoryStream::fork() const {
4186cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    SkAutoTUnref<SkMemoryStream> that(this->duplicate());
4196cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    that->seek(fOffset);
4206cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return that.detach();
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4236cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comsize_t SkMemoryStream::getLength() const {
4246cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return fData->size();
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4276cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comconst void* SkMemoryStream::getMemoryBase() {
4286cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return fData->data();
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4316cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comconst void* SkMemoryStream::getAtPos() {
4326cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com    return fData->bytes() + fOffset;
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////////////////////////////////
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////////////////////////////////
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFILEWStream::SkFILEWStream(const char path[])
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFILEWStream::~SkFILEWStream()
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
445eef834f2be2f8f97410fd1d897e9bb11597c6a40commit-bot@chromium.org    if (fFILE) {
4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_fclose(fFILE);
447eef834f2be2f8f97410fd1d897e9bb11597c6a40commit-bot@chromium.org    }
448eef834f2be2f8f97410fd1d897e9bb11597c6a40commit-bot@chromium.org}
449eef834f2be2f8f97410fd1d897e9bb11597c6a40commit-bot@chromium.org
450eef834f2be2f8f97410fd1d897e9bb11597c6a40commit-bot@chromium.orgsize_t SkFILEWStream::bytesWritten() const {
451eef834f2be2f8f97410fd1d897e9bb11597c6a40commit-bot@chromium.org    return sk_ftell(fFILE);
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkFILEWStream::write(const void* buffer, size_t size)
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
456eef834f2be2f8f97410fd1d897e9bb11597c6a40commit-bot@chromium.org    if (fFILE == NULL) {
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
458eef834f2be2f8f97410fd1d897e9bb11597c6a40commit-bot@chromium.org    }
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (sk_fwrite(buffer, size, fFILE) != size)
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_fclose(fFILE);
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFILE = NULL;
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFILEWStream::flush()
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
472eef834f2be2f8f97410fd1d897e9bb11597c6a40commit-bot@chromium.org    if (fFILE) {
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_fflush(fFILE);
474eef834f2be2f8f97410fd1d897e9bb11597c6a40commit-bot@chromium.org    }
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
484f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.orgbool SkMemoryWStream::write(const void* buffer, size_t size) {
485f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org    size = SkTMin(size, fMaxLength - fBytesWritten);
486f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org    if (size > 0) {
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memcpy(fBuffer + fBytesWritten, buffer, size);
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBytesWritten += size;
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDynamicMemoryWStream_MinBlockSize   256
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct SkDynamicMemoryWStream::Block {
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Block*  fNext;
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char*   fCurr;
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char*   fStop;
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* start() const { return (const char*)(this + 1); }
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char*   start() { return (char*)(this + 1); }
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t  avail() const { return fStop - fCurr; }
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t  written() const { return fCurr - this->start(); }
507fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void init(size_t size)
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fNext = NULL;
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurr = this->start();
5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStop = this->start() + size;
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
514fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const void* append(const void* data, size_t size)
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((size_t)(fStop - fCurr) >= size);
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memcpy(fCurr, data, size);
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCurr += size;
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return (const void*)((const char*)data + size);
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5248a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comSkDynamicMemoryWStream::SkDynamicMemoryWStream()
5258a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDynamicMemoryWStream::~SkDynamicMemoryWStream()
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    reset();
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDynamicMemoryWStream::reset()
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
5368a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    this->invalidateCopy();
537fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Block*  block = fHead;
539fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (block != NULL) {
5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        Block*  next = block->fNext;
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_free(block);
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        block = next;
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fHead = fTail = NULL;
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBytesWritten = 0;
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count > 0) {
5528a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        this->invalidateCopy();
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBytesWritten += count;
555fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        size_t  size;
557fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fTail != NULL && fTail->avail() > 0) {
559f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org            size = SkTMin(fTail->avail(), count);
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            buffer = fTail->append(buffer, size);
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(count >= size);
562fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            count -= size;
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count == 0)
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return true;
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
566fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
567f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org        size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize);
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        block->init(size);
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        block->append(buffer, count);
571fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fTail != NULL)
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fTail->fNext = block;
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        else
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fHead = fTail = block;
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTail = block;
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
5838a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    if (offset + count > fBytesWritten) {
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false; // test does not partially modify
5858a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    }
5868a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com
5878a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    this->invalidateCopy();
588fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Block* block = fHead;
5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (block != NULL) {
5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        size_t size = block->written();
5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (offset < size) {
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            size_t part = offset + count > size ? size - offset : count;
5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(block->start() + offset, buffer, part);
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= part)
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return true;
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count -= part;
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            buffer = (const void*) ((char* ) buffer + part);
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        offset = offset > size ? offset - size : 0;
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        block = block->fNext;
6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (offset + count > fBytesWritten)
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false; // test does not partially modify
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Block* block = fHead;
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (block != NULL) {
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        size_t size = block->written();
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (offset < size) {
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            size_t part = offset + count > size ? size - offset : count;
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(buffer, block->start() + offset, part);
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= part)
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                return true;
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            count -= part;
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            buffer = (void*) ((char* ) buffer + part);
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        offset = offset > size ? offset - size : 0;
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        block = block->fNext;
6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDynamicMemoryWStream::copyTo(void* dst) const
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
6298a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    if (fCopy) {
6308a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        memcpy(dst, fCopy->data(), fBytesWritten);
6318a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    } else {
6328a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        Block* block = fHead;
633fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
6348a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        while (block != NULL) {
6358a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com            size_t size = block->written();
6368a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com            memcpy(dst, block->start(), size);
6378a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com            dst = (void*)((char*)dst + size);
6388a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com            block = block->fNext;
6398a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        }
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDynamicMemoryWStream::padToAlign4()
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // cast to remove unary-minus warning
6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int padBytes = -(int)fBytesWritten & 0x03;
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (padBytes == 0)
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int zero = 0;
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    write(&zero, padBytes);
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6538a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comSkData* SkDynamicMemoryWStream::copyToData() const {
6548a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    if (NULL == fCopy) {
6558a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        void* buffer = sk_malloc_throw(fBytesWritten);
6568a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        this->copyTo(buffer);
6578a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        fCopy = SkData::NewFromMalloc(buffer, fBytesWritten);
6588a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    }
6598a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    fCopy->ref();
6608a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    return fCopy;
66170442a6cf73c9a822df23961f5e16dc3abc18f26reed@google.com}
66270442a6cf73c9a822df23961f5e16dc3abc18f26reed@google.com
6638a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.comvoid SkDynamicMemoryWStream::invalidateCopy() {
6648a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    if (fCopy) {
6658a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        fCopy->unref();
6668a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com        fCopy = NULL;
6678a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    }
66870442a6cf73c9a822df23961f5e16dc3abc18f26reed@google.com}
66970442a6cf73c9a822df23961f5e16dc3abc18f26reed@google.com
67088682b77d108a7413a166e3158e187f43211c46bbungeman@google.comclass SkBlockMemoryRefCnt : public SkRefCnt {
67188682b77d108a7413a166e3158e187f43211c46bbungeman@google.compublic:
67288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
67388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
67488682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    virtual ~SkBlockMemoryRefCnt() {
67588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        SkDynamicMemoryWStream::Block* block = fHead;
67688682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        while (block != NULL) {
67788682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            SkDynamicMemoryWStream::Block* next = block->fNext;
67888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            sk_free(block);
67988682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            block = next;
68088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        }
68188682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    }
68288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
68388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    SkDynamicMemoryWStream::Block* const fHead;
68488682b77d108a7413a166e3158e187f43211c46bbungeman@google.com};
68588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
68688682b77d108a7413a166e3158e187f43211c46bbungeman@google.comclass SkBlockMemoryStream : public SkStreamAsset {
68788682b77d108a7413a166e3158e187f43211c46bbungeman@google.compublic:
68888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
68988682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
69088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        , fSize(size) , fOffset(0), fCurrentOffset(0) { }
69188682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
69288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
69388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
69488682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        , fSize(size) , fOffset(0), fCurrentOffset(0) { }
69588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
69688682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE {
69788682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        size_t count = rawCount;
69888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        if (fOffset + count > fSize) {
69988682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            count = fSize - fOffset;
70088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        }
70188682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        size_t bytesLeftToRead = count;
70288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        while (fCurrent != NULL) {
70388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
7048d79f963b6431ee3759465eb2a6ea8d0c2ad2652bungeman@google.com            size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
70588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            if (buffer) {
70688682b77d108a7413a166e3158e187f43211c46bbungeman@google.com                memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
7078d79f963b6431ee3759465eb2a6ea8d0c2ad2652bungeman@google.com                buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
70888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            }
70988682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            if (bytesLeftToRead <= bytesFromCurrent) {
71088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com                fCurrentOffset += bytesFromCurrent;
71188682b77d108a7413a166e3158e187f43211c46bbungeman@google.com                fOffset += count;
71288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com                return count;
71388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            }
71488682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            bytesLeftToRead -= bytesFromCurrent;
71588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            fCurrent = fCurrent->fNext;
71688682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            fCurrentOffset = 0;
71788682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        }
71888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        SkASSERT(false);
71988682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        return 0;
72088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    }
72188682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
72288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    virtual bool isAtEnd() const SK_OVERRIDE {
72388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        return fOffset == fSize;
72488682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    }
72588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
72688682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    virtual bool rewind() SK_OVERRIDE {
72788682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        fCurrent = fBlockMemory->fHead;
72888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        fOffset = 0;
72988682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        fCurrentOffset = 0;
73088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        return true;
73188682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    }
73288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
73388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE {
73488682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
73588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    }
73688682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
73788682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    virtual size_t getPosition() const SK_OVERRIDE {
73888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        return fOffset;
73988682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    }
74088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
74188682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    virtual bool seek(size_t position) SK_OVERRIDE {
74288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        // If possible, skip forward.
74388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        if (position >= fOffset) {
74488682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            size_t skipAmount = position - fOffset;
74588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            return this->skip(skipAmount) == skipAmount;
74688682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        }
74788682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        // If possible, move backward within the current block.
74888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        size_t moveBackAmount = fOffset - position;
74988682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        if (moveBackAmount <= fCurrentOffset) {
75088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            fCurrentOffset -= moveBackAmount;
75188682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            fOffset -= moveBackAmount;
75288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            return true;
75388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        }
75488682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        // Otherwise rewind and move forward.
75588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        return this->rewind() && this->skip(position) == position;
75688682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    }
75788682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
75888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    virtual bool move(long offset) SK_OVERRIDE {
75988682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        return seek(fOffset + offset);
76088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    }
76188682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
76288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    virtual SkBlockMemoryStream* fork() const SK_OVERRIDE {
76388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate());
76488682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        that->fCurrent = this->fCurrent;
76588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        that->fOffset = this->fOffset;
76688682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        that->fCurrentOffset = this->fCurrentOffset;
76788682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        return that.detach();
76888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    }
76988682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
77088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    virtual size_t getLength() const SK_OVERRIDE {
77188682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        return fSize;
77288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    }
77388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
77488682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    virtual const void* getMemoryBase() SK_OVERRIDE {
77588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        if (NULL == fBlockMemory->fHead->fNext) {
77688682b77d108a7413a166e3158e187f43211c46bbungeman@google.com            return fBlockMemory->fHead->start();
77788682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        }
77888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        return NULL;
77988682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    }
78088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
78188682b77d108a7413a166e3158e187f43211c46bbungeman@google.comprivate:
78288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
78388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    SkDynamicMemoryWStream::Block const * fCurrent;
78488682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    size_t const fSize;
78588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    size_t fOffset;
78688682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    size_t fCurrentOffset;
78788682b77d108a7413a166e3158e187f43211c46bbungeman@google.com};
78888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
789c29f3d8c6dec938fd0599db30cae590fcaa2108bbungeman@google.comSkStreamAsset* SkDynamicMemoryWStream::detachAsStream() {
79088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    if (fCopy) {
79188682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy));
79288682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        this->reset();
79388682b77d108a7413a166e3158e187f43211c46bbungeman@google.com        return stream;
79488682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    }
79588682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten));
79688682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    fHead = 0;
79788682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    this->reset();
79888682b77d108a7413a166e3158e187f43211c46bbungeman@google.com    return stream;
79988682b77d108a7413a166e3158e187f43211c46bbungeman@google.com}
80088682b77d108a7413a166e3158e187f43211c46bbungeman@google.com
8018a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com///////////////////////////////////////////////////////////////////////////////
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDebugWStream::newline()
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
8057af56bee17764a0c118c8856a035bb3d27766969humper@google.com#if defined(SK_DEBUG) || defined(SK_DEVELOPER)
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDebugf("\n");
807490fb6b4713463954cc0283a9c30e754c45c6004commit-bot@chromium.org    fBytesWritten++;
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDebugWStream::write(const void* buffer, size_t size)
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
8137af56bee17764a0c118c8856a035bb3d27766969humper@google.com#if defined(SK_DEBUG) || defined(SK_DEVELOPER)
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char* s = new char[size+1];
8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    memcpy(s, buffer, size);
8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    s[size] = 0;
8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDebugf("%s", s);
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    delete[] s;
8190438645c72879d9b3441c8ce7eae0150e87f7393commit-bot@chromium.org    fBytesWritten += size;
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
823e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com
824e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com///////////////////////////////////////////////////////////////////////////////
825e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com///////////////////////////////////////////////////////////////////////////////
826e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com
8278eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com
8289711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.orgstatic SkData* mmap_filename(const char path[]) {
8299711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org    SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
8309711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org    if (NULL == file) {
8319711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org        return NULL;
832e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com    }
8338eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com
8349711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org    SkData* data = SkData::NewFromFILE(file);
8359711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org    sk_fclose(file);
8369711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org    return data;
837e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com}
838e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com
8396cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.comSkStreamAsset* SkStream::NewFromFile(const char path[]) {
8409711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org    SkAutoTUnref<SkData> data(mmap_filename(path));
8419711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org    if (data.get()) {
8429711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org        return SkNEW_ARGS(SkMemoryStream, (data.get()));
843e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com    }
8448eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com
845e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com    // If we get here, then our attempt at using mmap failed, so try normal
846e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com    // file access.
847e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com    SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path));
848e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com    if (!stream->isValid()) {
849e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com        stream->unref();
850e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com        stream = NULL;
851e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com    }
852e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com    return stream;
853e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com}
854