SkWriter32.h revision f6100c8b1aba89027cf74da8a324a744fd1d53fa
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.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.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkWriter32_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkWriter32_DEFINED
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTypes.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalar.h"
1694e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com#include "SkPath.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPoint.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRect.h"
194ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
202b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com#include "SkMatrix.h"
212b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com#include "SkRegion.h"
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkStream;
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkWStream;
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkWriter32 : SkNoncopyable {
275595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    struct BlockHeader;
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
29e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com    /**
30e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com     *  The caller can specify an initial block of storage, which the caller manages.
31e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com     *  SkWriter32 will not attempt to free this in its destructor. It is up to the
32e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com     *  implementation to decide if, and how much, of the storage to utilize, and it
33e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com     *  is possible that it may be ignored entirely.
34e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com     */
35e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com    SkWriter32(size_t minSize, void* initialStorage, size_t storageSize);
36e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com
37e1bc274295ec57cb3d3f01aaa8abff3b49c76c73vandebo@chromium.org    SkWriter32(size_t minSize)
38f6100c8b1aba89027cf74da8a324a744fd1d53famike@reedtribe.org        : fHead(NULL)
39f6100c8b1aba89027cf74da8a324a744fd1d53famike@reedtribe.org        , fTail(NULL)
40f6100c8b1aba89027cf74da8a324a744fd1d53famike@reedtribe.org        , fMinSize(minSize)
41f6100c8b1aba89027cf74da8a324a744fd1d53famike@reedtribe.org        , fSize(0)
42f6100c8b1aba89027cf74da8a324a744fd1d53famike@reedtribe.org        , fWrittenBeforeLastBlock(0)
43f6100c8b1aba89027cf74da8a324a744fd1d53famike@reedtribe.org        {}
44e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkWriter32();
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
471cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    // return the current offset (will always be a multiple of 4)
481cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    uint32_t bytesWritten() const { return fSize; }
491cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    // DEPRECATED: use byetsWritten instead
501cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    uint32_t  size() const { return this->bytesWritten(); }
511cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
521cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    void      reset();
53b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
545595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    // size MUST be multiple of 4
555595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    uint32_t* reserve(size_t size) {
565595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        SkASSERT(SkAlign4(size) == size);
57b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
585595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        Block* block = fTail;
595595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        if (NULL == block || block->available() < size) {
605595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block = this->doReserve(size);
615595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        }
625595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        fSize += size;
635595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        return block->alloc(size);
645595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    }
65a27096b4740775ae141fd0abaf456d706065c5eeskia.committer@gmail.com
665595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    void reset(void* storage, size_t size);
67e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool writeBool(bool value) {
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->writeInt(value);
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return value;
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
72fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeInt(int32_t value) {
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value;
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
76fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write8(int32_t value) {
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF;
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
80fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write16(int32_t value) {
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF;
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
84fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write32(int32_t value) {
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value;
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
88fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
8951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    void writePtr(void* ptr) {
9051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        // Since we "know" that we're always 4-byte aligned, we can tell the
9151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        // compiler that here, by assigning to an int32 ptr.
9251c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        int32_t* addr = (int32_t*)this->reserve(sizeof(void*));
9351c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        if (4 == sizeof(void*)) {
9451c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com            *(void**)addr = ptr;
9551c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        } else {
9651c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com            memcpy(addr, &ptr, sizeof(void*));
9751c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        }
9851c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    }
9951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeScalar(SkScalar value) {
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkScalar*)this->reserve(sizeof(value)) = value;
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
103fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writePoint(const SkPoint& pt) {
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkPoint*)this->reserve(sizeof(pt)) = pt;
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
107fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeRect(const SkRect& rect) {
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkRect*)this->reserve(sizeof(rect)) = rect;
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
111306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
1124ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    void writeRRect(const SkRRect& rrect) {
1134ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory));
1144ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
115306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
11694e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    void writePath(const SkPath& path) {
11794e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        size_t size = path.writeToMemory(NULL);
11894e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        SkASSERT(SkAlign4(size) == size);
11994e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        path.writeToMemory(this->reserve(size));
12094e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    }
12194e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com
1222b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    void writeMatrix(const SkMatrix& matrix) {
12394e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        size_t size = matrix.writeToMemory(NULL);
1242b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com        SkASSERT(SkAlign4(size) == size);
12594e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        matrix.writeToMemory(this->reserve(size));
1262b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    }
127fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1282b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    void writeRegion(const SkRegion& rgn) {
12994e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        size_t size = rgn.writeToMemory(NULL);
1302b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com        SkASSERT(SkAlign4(size) == size);
13194e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        rgn.writeToMemory(this->reserve(size));
1322b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    }
1332b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // write count bytes (must be a multiple of 4)
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeMul4(const void* values, size_t size) {
1365b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com        this->write(values, size);
1375b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    }
1385b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com
1395b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    /**
1405b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     *  Write size bytes from values. size must be a multiple of 4, though
1415b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     *  values need not be 4-byte aligned.
1425b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     */
1435b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    void write(const void* values, size_t size) {
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkAlign4(size) == size);
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // if we could query how much is avail in the current block, we might
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // copy that much, and then alloc the rest. That would reduce the waste
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // in the current block
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memcpy(this->reserve(size), values, size);
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
150fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1515a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com    /**
1525a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be
1535a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  filled in with zeroes.
1545a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     */
1555a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com    uint32_t* reservePad(size_t size);
1565a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com
1575a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com    /**
1585a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  Write size bytes from src, and pad to 4 byte alignment with zeroes.
1595a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     */
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writePad(const void* src, size_t size);
161dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
162dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    /**
163dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  Writes a string to the writer, which can be retrieved with
164dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  SkReader32::readString().
165dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  The length can be specified, or if -1 is passed, it will be computed by
166dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  calling strlen(). The length must be < 0xFFFF
167dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     */
168dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    void writeString(const char* str, size_t len = (size_t)-1);
169dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
170dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    /**
171dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  Computes the size (aligned to multiple of 4) need to write the string
172dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  in a call to writeString(). If the length is not specified, it will be
173dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  computed by calling strlen().
174dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     */
175dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    static size_t WriteStringSize(const char* str, size_t len = (size_t)-1);
176dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return the address of the 4byte int at the specified offset (which must
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // be a multiple of 4. This does not allocate any new space, so the returned
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // address is only valid for 1 int.
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t* peek32(size_t offset);
181fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1821cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    /**
1831cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     *  Move the cursor back to offset bytes from the beginning.
1841cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     *  This has the same restrictions as peek32: offset must be <= size() and
1851cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     *  offset must be a multiple of 4.
1861cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     */
1871cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    void rewindToOffset(size_t offset);
1881cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // copy into a single buffer (allocated by caller). Must be at least size()
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void flatten(void* dst) const;
191fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // read from the stream, and write up to length bytes. Return the actual
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // number of bytes written.
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t readFromStream(SkStream*, size_t length);
195fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool writeToStream(SkWStream*);
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1995595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    struct Block {
2005595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        Block*  fNext;
2015595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        char*   fBasePtr;
2025595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        size_t  fSizeOfBlock;      // total space allocated (after this)
2035595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        size_t  fAllocatedSoFar;    // space used so far
2045595af1b2ebe6590e98641464d43d22281a7f295reed@google.com
2055595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        size_t  available() const { return fSizeOfBlock - fAllocatedSoFar; }
2065595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        char*   base() { return fBasePtr; }
2075595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        const char* base() const { return fBasePtr; }
2085595af1b2ebe6590e98641464d43d22281a7f295reed@google.com
2095595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        uint32_t* alloc(size_t size) {
2105595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(SkAlign4(size) == size);
2115595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(this->available() >= size);
2125595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            void* ptr = this->base() + fAllocatedSoFar;
2135595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            fAllocatedSoFar += size;
2145595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(fAllocatedSoFar <= fSizeOfBlock);
2155595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            return (uint32_t*)ptr;
2165595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        }
217acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com
2185595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        uint32_t* peek32(size_t offset) {
2195595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(offset <= fAllocatedSoFar + 4);
2205595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            void* ptr = this->base() + offset;
2215595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            return (uint32_t*)ptr;
2225595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        }
223b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
2245595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        void rewind() {
2255595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            fNext = NULL;
2265595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            fAllocatedSoFar = 0;
2275595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            // keep fSizeOfBlock as is
2285595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        }
229b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
2305595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        static Block* Create(size_t size) {
2315595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(SkIsAlign4(size));
2325595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
2335595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fNext = NULL;
2345595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fBasePtr = (char*)(block + 1);
2355595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fSizeOfBlock = size;
2365595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fAllocatedSoFar = 0;
2375595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            return block;
2385595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        }
239e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com
2405595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        Block* initFromStorage(void* storage, size_t size) {
2415595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(SkIsAlign4((intptr_t)storage));
2425595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(SkIsAlign4(size));
2435595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            Block* block = this;
2445595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fNext = NULL;
2455595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fBasePtr = (char*)storage;
2465595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fSizeOfBlock = size;
2475595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fAllocatedSoFar = 0;
2485595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            return block;
2495595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        }
2505595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    };
2515595af1b2ebe6590e98641464d43d22281a7f295reed@google.com
2525595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    enum {
2535595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        MIN_BLOCKSIZE = sizeof(SkWriter32::Block) + sizeof(intptr_t)
2545595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    };
255b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
2565595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    Block       fExternalBlock;
2575595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    Block*      fHead;
2585595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    Block*      fTail;
2595595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    size_t      fMinSize;
2605595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    uint32_t    fSize;
261f56225c848cb0cd0fde4cb37558174ae096b93d1reed@google.com    // sum of bytes written in all blocks *before* fTail
262f56225c848cb0cd0fde4cb37558174ae096b93d1reed@google.com    uint32_t    fWrittenBeforeLastBlock;
263f56225c848cb0cd0fde4cb37558174ae096b93d1reed@google.com
2645595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    bool isHeadExternallyAllocated() const {
2655595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        return fHead == &fExternalBlock;
2665595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    }
267e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Block* newBlock(size_t bytes);
269b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
2705595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    // only call from reserve()
2715595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    Block* doReserve(size_t bytes);
2721cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
2731cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    SkDEBUGCODE(void validate() const;)
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27651c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com/**
27751c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  Helper class to allocated SIZE bytes as part of the writer, and to provide
27851c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  that storage to the constructor as its initial storage buffer.
27951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *
28051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  This wrapper ensures proper alignment rules are met for the storage.
28151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com */
28251c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.comtemplate <size_t SIZE> class SkSWriter32 : public SkWriter32 {
28351c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.compublic:
28451c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    SkSWriter32(size_t minSize) : SkWriter32(minSize, fData.fStorage, SIZE) {}
285fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
28651c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.comprivate:
28751c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    union {
28851c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        void*   fPtrAlignment;
28951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        double  fDoubleAlignment;
29051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        char    fStorage[SIZE];
29151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    } fData;
29251c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com};
29351c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
295