SkWriter32.h revision adacc7067ad617cdc7bbef39192ca80f4b4d27f9
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)
48adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    size_t bytesWritten() const { return fSize; }
49ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org    // DEPRECATED: use bytesWritten instead  TODO(mtklein): clean up
50adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    size_t size() const { return this->bytesWritten(); }
511cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
52ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org    // Returns true if we've written only into the storage passed into constructor or reset.
53ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org    // (You may be able to use this to avoid a call to flatten.)
54ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org    bool wroteOnlyToStorage() const {
55ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org        return fHead == &fExternalBlock && this->bytesWritten() <= fExternalBlock.fSizeOfBlock;
56ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org    }
57ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org
58ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org    void reset();
59ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org    void reset(void* storage, size_t size);
60b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
615595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    // size MUST be multiple of 4
625595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    uint32_t* reserve(size_t size) {
635595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        SkASSERT(SkAlign4(size) == size);
64b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
655595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        Block* block = fTail;
665595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        if (NULL == block || block->available() < size) {
675595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block = this->doReserve(size);
685595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        }
695595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        fSize += size;
705595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        return block->alloc(size);
715595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    }
72a27096b4740775ae141fd0abaf456d706065c5eeskia.committer@gmail.com
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool writeBool(bool value) {
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->writeInt(value);
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return value;
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
77fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeInt(int32_t value) {
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value;
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
81fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write8(int32_t value) {
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF;
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
85fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write16(int32_t value) {
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF;
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
89fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write32(int32_t value) {
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value;
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
93fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
9451c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    void writePtr(void* ptr) {
9551c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        // Since we "know" that we're always 4-byte aligned, we can tell the
9651c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        // compiler that here, by assigning to an int32 ptr.
9751c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        int32_t* addr = (int32_t*)this->reserve(sizeof(void*));
9851c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        if (4 == sizeof(void*)) {
9951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com            *(void**)addr = ptr;
10051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        } else {
10151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com            memcpy(addr, &ptr, sizeof(void*));
10251c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        }
10351c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    }
10451c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeScalar(SkScalar value) {
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkScalar*)this->reserve(sizeof(value)) = value;
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
108fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writePoint(const SkPoint& pt) {
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkPoint*)this->reserve(sizeof(pt)) = pt;
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
112fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeRect(const SkRect& rect) {
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkRect*)this->reserve(sizeof(rect)) = rect;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
116306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
1175587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com    void writeIRect(const SkIRect& rect) {
1185587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com        *(SkIRect*)this->reserve(sizeof(rect)) = rect;
1195587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com    }
1205587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com
1214ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    void writeRRect(const SkRRect& rrect) {
1224ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory));
1234ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
124306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
12594e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    void writePath(const SkPath& path) {
12694e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        size_t size = path.writeToMemory(NULL);
12794e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        SkASSERT(SkAlign4(size) == size);
12894e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        path.writeToMemory(this->reserve(size));
12994e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    }
13094e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com
1312b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    void writeMatrix(const SkMatrix& matrix) {
13294e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        size_t size = matrix.writeToMemory(NULL);
1332b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com        SkASSERT(SkAlign4(size) == size);
13494e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        matrix.writeToMemory(this->reserve(size));
1352b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    }
136fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1372b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    void writeRegion(const SkRegion& rgn) {
13894e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        size_t size = rgn.writeToMemory(NULL);
1392b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com        SkASSERT(SkAlign4(size) == size);
14094e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        rgn.writeToMemory(this->reserve(size));
1412b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    }
1422b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // write count bytes (must be a multiple of 4)
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeMul4(const void* values, size_t size) {
1455b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com        this->write(values, size);
1465b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    }
1475b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com
1485b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    /**
1495b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     *  Write size bytes from values. size must be a multiple of 4, though
1505b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     *  values need not be 4-byte aligned.
1515b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     */
1525b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    void write(const void* values, size_t size) {
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkAlign4(size) == size);
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // if we could query how much is avail in the current block, we might
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // copy that much, and then alloc the rest. That would reduce the waste
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // in the current block
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memcpy(this->reserve(size), values, size);
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
159fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1605a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com    /**
1615a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be
1625a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  filled in with zeroes.
1635a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     */
1645a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com    uint32_t* reservePad(size_t size);
1655a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com
1665a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com    /**
1675a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  Write size bytes from src, and pad to 4 byte alignment with zeroes.
1685a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     */
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writePad(const void* src, size_t size);
170dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
171dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    /**
172dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  Writes a string to the writer, which can be retrieved with
173dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  SkReader32::readString().
174dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  The length can be specified, or if -1 is passed, it will be computed by
1750038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com     *  calling strlen(). The length must be < max size_t.
1760038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com     *
1770038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com     *  If you write NULL, it will be read as "".
178dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     */
179dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    void writeString(const char* str, size_t len = (size_t)-1);
180dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
181dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    /**
182dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  Computes the size (aligned to multiple of 4) need to write the string
183dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  in a call to writeString(). If the length is not specified, it will be
184dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  computed by calling strlen().
185dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     */
186dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    static size_t WriteStringSize(const char* str, size_t len = (size_t)-1);
187dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return the address of the 4byte int at the specified offset (which must
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // be a multiple of 4. This does not allocate any new space, so the returned
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // address is only valid for 1 int.
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t* peek32(size_t offset);
192fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1931cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    /**
1941cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     *  Move the cursor back to offset bytes from the beginning.
1951cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     *  This has the same restrictions as peek32: offset must be <= size() and
1961cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     *  offset must be a multiple of 4.
1971cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     */
1981cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    void rewindToOffset(size_t offset);
1991cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // copy into a single buffer (allocated by caller). Must be at least size()
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void flatten(void* dst) const;
202fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // read from the stream, and write up to length bytes. Return the actual
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // number of bytes written.
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t readFromStream(SkStream*, size_t length);
206fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool writeToStream(SkWStream*);
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
2105595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    struct Block {
2115595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        Block*  fNext;
2125595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        char*   fBasePtr;
2135595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        size_t  fSizeOfBlock;      // total space allocated (after this)
2145595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        size_t  fAllocatedSoFar;    // space used so far
2155595af1b2ebe6590e98641464d43d22281a7f295reed@google.com
2165595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        size_t  available() const { return fSizeOfBlock - fAllocatedSoFar; }
2175595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        char*   base() { return fBasePtr; }
2185595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        const char* base() const { return fBasePtr; }
2195595af1b2ebe6590e98641464d43d22281a7f295reed@google.com
2205595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        uint32_t* alloc(size_t size) {
2215595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(SkAlign4(size) == size);
2225595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(this->available() >= size);
2235595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            void* ptr = this->base() + fAllocatedSoFar;
2245595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            fAllocatedSoFar += size;
2255595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(fAllocatedSoFar <= fSizeOfBlock);
2265595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            return (uint32_t*)ptr;
2275595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        }
228acd471f47ccfb97cf2f2f00dc01cd1fd45bc1ef2reed@google.com
2295595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        uint32_t* peek32(size_t offset) {
2305595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(offset <= fAllocatedSoFar + 4);
2315595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            void* ptr = this->base() + offset;
2325595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            return (uint32_t*)ptr;
2335595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        }
234b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
2355595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        void rewind() {
2365595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            fNext = NULL;
2375595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            fAllocatedSoFar = 0;
2385595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            // keep fSizeOfBlock as is
2395595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        }
240b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
2415595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        static Block* Create(size_t size) {
2425595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(SkIsAlign4(size));
2435595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
2445595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fNext = NULL;
2455595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fBasePtr = (char*)(block + 1);
2465595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fSizeOfBlock = size;
2475595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fAllocatedSoFar = 0;
2485595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            return block;
2495595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        }
250e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com
2515595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        Block* initFromStorage(void* storage, size_t size) {
2525595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(SkIsAlign4((intptr_t)storage));
2535595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            SkASSERT(SkIsAlign4(size));
2545595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            Block* block = this;
2555595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fNext = NULL;
2565595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fBasePtr = (char*)storage;
2575595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fSizeOfBlock = size;
2585595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            block->fAllocatedSoFar = 0;
2595595af1b2ebe6590e98641464d43d22281a7f295reed@google.com            return block;
2605595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        }
2615595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    };
2625595af1b2ebe6590e98641464d43d22281a7f295reed@google.com
2635595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    enum {
2645595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        MIN_BLOCKSIZE = sizeof(SkWriter32::Block) + sizeof(intptr_t)
2655595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    };
266b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
2675595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    Block       fExternalBlock;
2685595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    Block*      fHead;
2695595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    Block*      fTail;
2705595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    size_t      fMinSize;
271adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    size_t      fSize;
272f56225c848cb0cd0fde4cb37558174ae096b93d1reed@google.com    // sum of bytes written in all blocks *before* fTail
273adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    size_t      fWrittenBeforeLastBlock;
274f56225c848cb0cd0fde4cb37558174ae096b93d1reed@google.com
2755595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    bool isHeadExternallyAllocated() const {
2765595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        return fHead == &fExternalBlock;
2775595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    }
278e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Block* newBlock(size_t bytes);
280b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
2815595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    // only call from reserve()
2825595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    Block* doReserve(size_t bytes);
2831cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
2841cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    SkDEBUGCODE(void validate() const;)
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28751c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com/**
28851c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  Helper class to allocated SIZE bytes as part of the writer, and to provide
28951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  that storage to the constructor as its initial storage buffer.
29051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *
29151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  This wrapper ensures proper alignment rules are met for the storage.
29251c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com */
29351c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.comtemplate <size_t SIZE> class SkSWriter32 : public SkWriter32 {
29451c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.compublic:
29551c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    SkSWriter32(size_t minSize) : SkWriter32(minSize, fData.fStorage, SIZE) {}
296fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
29751c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.comprivate:
29851c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    union {
29951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        void*   fPtrAlignment;
30051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        double  fDoubleAlignment;
30151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        char    fStorage[SIZE];
30251c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    } fData;
30351c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com};
30451c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
306