180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2008 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef SkWriter32_DEFINED
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkWriter32_DEFINED
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTypes.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkScalar.h"
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPath.h"
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPoint.h"
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRect.h"
19363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkRRect.h"
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMatrix.h"
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRegion.h"
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkStream;
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkWStream;
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkWriter32 : SkNoncopyable {
27d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    struct BlockHeader;
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  The caller can specify an initial block of storage, which the caller manages.
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  SkWriter32 will not attempt to free this in its destructor. It is up to the
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  implementation to decide if, and how much, of the storage to utilize, and it
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  is possible that it may be ignored entirely.
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkWriter32(size_t minSize, void* initialStorage, size_t storageSize);
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkWriter32(size_t minSize)
38d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        : fHead(NULL)
39d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        , fTail(NULL)
40d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        , fMinSize(minSize)
41d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        , fSize(0)
42d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        , fWrittenBeforeLastBlock(0)
43d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        {}
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ~SkWriter32();
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // return the current offset (will always be a multiple of 4)
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t bytesWritten() const { return fSize; }
4958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    // DEPRECATED: use bytesWritten instead  TODO(mtklein): clean up
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t  size() const { return this->bytesWritten(); }
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    // Returns true if we've written only into the storage passed into constructor or reset.
5358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    // (You may be able to use this to avoid a call to flatten.)
5458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    bool wroteOnlyToStorage() const {
5558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return fHead == &fExternalBlock && this->bytesWritten() <= fExternalBlock.fSizeOfBlock;
5658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
5758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
5858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    void reset();
5958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    void reset(void* storage, size_t size);
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // size MUST be multiple of 4
62d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    uint32_t* reserve(size_t size) {
63d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        SkASSERT(SkAlign4(size) == size);
64d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
65d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        Block* block = fTail;
66d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (NULL == block || block->available() < size) {
67d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            block = this->doReserve(size);
68d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
69d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        fSize += size;
70d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return block->alloc(size);
71d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
72d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool writeBool(bool value) {
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->writeInt(value);
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return value;
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void writeInt(int32_t value) {
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *(int32_t*)this->reserve(sizeof(value)) = value;
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void write8(int32_t value) {
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF;
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void write16(int32_t value) {
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF;
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void write32(int32_t value) {
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *(int32_t*)this->reserve(sizeof(value)) = value;
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void writePtr(void* ptr) {
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Since we "know" that we're always 4-byte aligned, we can tell the
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // compiler that here, by assigning to an int32 ptr.
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int32_t* addr = (int32_t*)this->reserve(sizeof(void*));
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (4 == sizeof(void*)) {
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *(void**)addr = ptr;
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            memcpy(addr, &ptr, sizeof(void*));
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void writeScalar(SkScalar value) {
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *(SkScalar*)this->reserve(sizeof(value)) = value;
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void writePoint(const SkPoint& pt) {
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *(SkPoint*)this->reserve(sizeof(pt)) = pt;
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void writeRect(const SkRect& rect) {
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *(SkRect*)this->reserve(sizeof(rect)) = rect;
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
117fa0ab893eb60a41aac6945ab26d2b3a7e38443c4Derek Sollenberger    void writeIRect(const SkIRect& rect) {
118fa0ab893eb60a41aac6945ab26d2b3a7e38443c4Derek Sollenberger        *(SkIRect*)this->reserve(sizeof(rect)) = rect;
119fa0ab893eb60a41aac6945ab26d2b3a7e38443c4Derek Sollenberger    }
120fa0ab893eb60a41aac6945ab26d2b3a7e38443c4Derek Sollenberger
121363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void writeRRect(const SkRRect& rrect) {
122363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory));
123363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
124363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void writePath(const SkPath& path) {
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t size = path.writeToMemory(NULL);
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(SkAlign4(size) == size);
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        path.writeToMemory(this->reserve(size));
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void writeMatrix(const SkMatrix& matrix) {
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t size = matrix.writeToMemory(NULL);
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(SkAlign4(size) == size);
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        matrix.writeToMemory(this->reserve(size));
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void writeRegion(const SkRegion& rgn) {
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t size = rgn.writeToMemory(NULL);
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(SkAlign4(size) == size);
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rgn.writeToMemory(this->reserve(size));
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // write count bytes (must be a multiple of 4)
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void writeMul4(const void* values, size_t size) {
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->write(values, size);
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  Write size bytes from values. size must be a multiple of 4, though
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  values need not be 4-byte aligned.
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void write(const void* values, size_t size) {
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(SkAlign4(size) == size);
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // if we could query how much is avail in the current block, we might
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // copy that much, and then alloc the rest. That would reduce the waste
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // in the current block
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(this->reserve(size), values, size);
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  filled in with zeroes.
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t* reservePad(size_t size);
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  Write size bytes from src, and pad to 4 byte alignment with zeroes.
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void writePad(const void* src, size_t size);
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  Writes a string to the writer, which can be retrieved with
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  SkReader32::readString().
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  The length can be specified, or if -1 is passed, it will be computed by
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  calling strlen(). The length must be < 0xFFFF
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void writeString(const char* str, size_t len = (size_t)-1);
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  Computes the size (aligned to multiple of 4) need to write the string
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  in a call to writeString(). If the length is not specified, it will be
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  computed by calling strlen().
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static size_t WriteStringSize(const char* str, size_t len = (size_t)-1);
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // return the address of the 4byte int at the specified offset (which must
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // be a multiple of 4. This does not allocate any new space, so the returned
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // address is only valid for 1 int.
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t* peek32(size_t offset);
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  Move the cursor back to offset bytes from the beginning.
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  This has the same restrictions as peek32: offset must be <= size() and
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     *  offset must be a multiple of 4.
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void rewindToOffset(size_t offset);
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // copy into a single buffer (allocated by caller). Must be at least size()
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void flatten(void* dst) const;
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // read from the stream, and write up to length bytes. Return the actual
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // number of bytes written.
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t readFromStream(SkStream*, size_t length);
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool writeToStream(SkWStream*);
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
208d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    struct Block {
209d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        Block*  fNext;
210d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        char*   fBasePtr;
211d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        size_t  fSizeOfBlock;      // total space allocated (after this)
212d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        size_t  fAllocatedSoFar;    // space used so far
213d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
214d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        size_t  available() const { return fSizeOfBlock - fAllocatedSoFar; }
215d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        char*   base() { return fBasePtr; }
216d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        const char* base() const { return fBasePtr; }
217d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
218d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        uint32_t* alloc(size_t size) {
219d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            SkASSERT(SkAlign4(size) == size);
220d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            SkASSERT(this->available() >= size);
221d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            void* ptr = this->base() + fAllocatedSoFar;
222d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            fAllocatedSoFar += size;
223d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            SkASSERT(fAllocatedSoFar <= fSizeOfBlock);
224d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            return (uint32_t*)ptr;
225d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
227d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        uint32_t* peek32(size_t offset) {
228d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            SkASSERT(offset <= fAllocatedSoFar + 4);
229d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            void* ptr = this->base() + offset;
230d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            return (uint32_t*)ptr;
231d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
232d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
233d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        void rewind() {
234d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            fNext = NULL;
235d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            fAllocatedSoFar = 0;
236d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            // keep fSizeOfBlock as is
237d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
238d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
239d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        static Block* Create(size_t size) {
240d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            SkASSERT(SkIsAlign4(size));
241d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
242d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            block->fNext = NULL;
243d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            block->fBasePtr = (char*)(block + 1);
244d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            block->fSizeOfBlock = size;
245d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            block->fAllocatedSoFar = 0;
246d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            return block;
247d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
248d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
249d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        Block* initFromStorage(void* storage, size_t size) {
250d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            SkASSERT(SkIsAlign4((intptr_t)storage));
251d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            SkASSERT(SkIsAlign4(size));
252d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            Block* block = this;
253d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            block->fNext = NULL;
254d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            block->fBasePtr = (char*)storage;
255d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            block->fSizeOfBlock = size;
256d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            block->fAllocatedSoFar = 0;
257d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            return block;
258d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        }
259d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    };
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
261d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    enum {
262d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        MIN_BLOCKSIZE = sizeof(SkWriter32::Block) + sizeof(intptr_t)
263d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    };
264d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
265d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    Block       fExternalBlock;
266d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    Block*      fHead;
267d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    Block*      fTail;
268d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    size_t      fMinSize;
269d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    uint32_t    fSize;
270363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // sum of bytes written in all blocks *before* fTail
271363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    uint32_t    fWrittenBeforeLastBlock;
272363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
273d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    bool isHeadExternallyAllocated() const {
274d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return fHead == &fExternalBlock;
275d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Block* newBlock(size_t bytes);
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
279d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // only call from reserve()
280d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    Block* doReserve(size_t bytes);
281d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(void validate() const;)
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  Helper class to allocated SIZE bytes as part of the writer, and to provide
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  that storage to the constructor as its initial storage buffer.
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *  This wrapper ensures proper alignment rules are met for the storage.
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate <size_t SIZE> class SkSWriter32 : public SkWriter32 {
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSWriter32(size_t minSize) : SkWriter32(minSize, fData.fStorage, SIZE) {}
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    union {
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        void*   fPtrAlignment;
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        double  fDoubleAlignment;
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char    fStorage[SIZE];
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } fData;
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
304