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
13c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org#include "SkData.h"
1419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkMatrix.h"
1594e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com#include "SkPath.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPoint.h"
174ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
1819382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkRect.h"
192b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com#include "SkRegion.h"
2019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkScalar.h"
2119382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkStream.h"
22ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org#include "SkTemplates.h"
2319382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkTypes.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkWriter32 : SkNoncopyable {
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
27e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com    /**
28e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com     *  The caller can specify an initial block of storage, which the caller manages.
2919382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org     *
3019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org     *  SkWriter32 will try to back reserve and write calls with this external storage until the
3119382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org     *  first time an allocation doesn't fit.  From then it will use dynamically allocated storage.
3219382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org     *  This used to be optional behavior, but pipe now relies on it.
33e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com     */
34ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    SkWriter32(void* external = NULL, size_t externalBytes = 0) {
3519382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        this->reset(external, externalBytes);
3619382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
381cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    // return the current offset (will always be a multiple of 4)
39046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    size_t bytesWritten() const { return fUsed; }
404469938e92d779dff05e745559e67907bbf21e78reed@google.com
414469938e92d779dff05e745559e67907bbf21e78reed@google.com    SK_ATTR_DEPRECATED("use bytesWritten")
42adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    size_t size() const { return this->bytesWritten(); }
431cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
4419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void reset(void* external = NULL, size_t externalBytes = 0) {
4519382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        SkASSERT(SkIsAlign4((uintptr_t)external));
4619382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        SkASSERT(SkIsAlign4(externalBytes));
47046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org
48c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org        fSnapshot.reset(NULL);
49046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fData = (uint8_t*)external;
50046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fCapacity = externalBytes;
51046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fUsed = 0;
52046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fExternal = external;
53ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org    }
54ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org
55046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    // Returns the current buffer.
56046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    // The pointer may be invalidated by any future write calls.
5719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    const uint32_t* contiguousArray() const {
58046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        return (uint32_t*)fData;
5919382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
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);
64046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        size_t offset = fUsed;
65046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        size_t totalRequired = fUsed + size;
66046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        if (totalRequired > fCapacity) {
67a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org            this->growToAtLeast(totalRequired);
6819382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        }
69046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fUsed = totalRequired;
70046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        return (uint32_t*)(fData + offset);
7119382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
72b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
73536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    /**
74536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org     *  Read a T record at offset, which must be a multiple of 4. Only legal if the record
75c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  was written atomically using the write methods below.
76536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org     */
77536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    template<typename T>
78536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    const T& readTAt(size_t offset) const {
79046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(SkAlign4(offset) == offset);
80046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(offset < fUsed);
81536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        return *(T*)(fData + offset);
82046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    }
83046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org
84536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    /**
85536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org     *  Overwrite a T record at offset, which must be a multiple of 4. Only legal if the record
86c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  was written atomically using the write methods below.
87536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org     */
88536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    template<typename T>
89536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    void overwriteTAt(size_t offset, const T& value) {
90046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(SkAlign4(offset) == offset);
91046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(offset < fUsed);
92c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org        SkASSERT(fSnapshot.get() == NULL);
93536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        *(T*)(fData + offset) = value;
94046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    }
95a27096b4740775ae141fd0abaf456d706065c5eeskia.committer@gmail.com
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool writeBool(bool value) {
9719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        this->write32(value);
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return value;
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
100fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeInt(int32_t value) {
10219382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        this->write32(value);
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
104fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write8(int32_t value) {
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF;
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
108fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write16(int32_t value) {
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF;
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
112fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write32(int32_t value) {
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
116fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
11719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void writePtr(void* value) {
11819382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        *(void**)this->reserve(sizeof(value)) = value;
11951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    }
12051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeScalar(SkScalar value) {
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkScalar*)this->reserve(sizeof(value)) = value;
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
124fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writePoint(const SkPoint& pt) {
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkPoint*)this->reserve(sizeof(pt)) = pt;
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
128fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeRect(const SkRect& rect) {
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkRect*)this->reserve(sizeof(rect)) = rect;
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
132306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
1335587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com    void writeIRect(const SkIRect& rect) {
1345587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com        *(SkIRect*)this->reserve(sizeof(rect)) = rect;
1355587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com    }
1365587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com
1374ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    void writeRRect(const SkRRect& rrect) {
1384ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory));
1394ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
140306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
14194e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    void writePath(const SkPath& path) {
14294e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        size_t size = path.writeToMemory(NULL);
14394e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        SkASSERT(SkAlign4(size) == size);
14494e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        path.writeToMemory(this->reserve(size));
14594e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    }
14694e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com
1472b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    void writeMatrix(const SkMatrix& matrix) {
14894e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        size_t size = matrix.writeToMemory(NULL);
1492b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com        SkASSERT(SkAlign4(size) == size);
15094e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        matrix.writeToMemory(this->reserve(size));
1512b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    }
152fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1532b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    void writeRegion(const SkRegion& rgn) {
15494e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        size_t size = rgn.writeToMemory(NULL);
1552b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com        SkASSERT(SkAlign4(size) == size);
15694e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        rgn.writeToMemory(this->reserve(size));
1572b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    }
1582b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // write count bytes (must be a multiple of 4)
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeMul4(const void* values, size_t size) {
1615b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com        this->write(values, size);
1625b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    }
1635b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com
1645b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    /**
1655b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     *  Write size bytes from values. size must be a multiple of 4, though
1665b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     *  values need not be 4-byte aligned.
1675b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     */
1685b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    void write(const void* values, size_t size) {
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkAlign4(size) == size);
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memcpy(this->reserve(size), values, size);
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
172fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1735a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com    /**
1745a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be
1755a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  filled in with zeroes.
1765a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     */
17719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    uint32_t* reservePad(size_t size) {
178536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        size_t alignedSize = SkAlign4(size);
179536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        uint32_t* p = this->reserve(alignedSize);
180536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        if (alignedSize != size) {
181536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org            SkASSERT(alignedSize >= 4);
182536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org            p[alignedSize / 4 - 1] = 0;
18319382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        }
18419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        return p;
18519382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
1865a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com
1875a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com    /**
1885a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  Write size bytes from src, and pad to 4 byte alignment with zeroes.
1895a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     */
19019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void writePad(const void* src, size_t size) {
19119382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        memcpy(this->reservePad(size), src, size);
19219382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
193dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
194dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    /**
195dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  Writes a string to the writer, which can be retrieved with
196dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  SkReader32::readString().
197dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  The length can be specified, or if -1 is passed, it will be computed by
1980038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com     *  calling strlen(). The length must be < max size_t.
1990038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com     *
2000038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com     *  If you write NULL, it will be read as "".
201dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     */
202dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    void writeString(const char* str, size_t len = (size_t)-1);
203dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
204dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    /**
205dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  Computes the size (aligned to multiple of 4) need to write the string
206dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  in a call to writeString(). If the length is not specified, it will be
207dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  computed by calling strlen().
208dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     */
209dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    static size_t WriteStringSize(const char* str, size_t len = (size_t)-1);
210dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
2111cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    /**
2121cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     *  Move the cursor back to offset bytes from the beginning.
213c6d3c444ca76feba5a8937dbc80626ade5347275commit-bot@chromium.org     *  offset must be a multiple of 4 no greater than size().
2141cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     */
21519382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void rewindToOffset(size_t offset) {
21619382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        SkASSERT(SkAlign4(offset) == offset);
217046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(offset <= bytesWritten());
218046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fUsed = offset;
21919382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
2201cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // copy into a single buffer (allocated by caller). Must be at least size()
22219382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void flatten(void* dst) const {
223046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        memcpy(dst, fData, fUsed);
22419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
22519382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org
22619382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    bool writeToStream(SkWStream* stream) const {
227046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        return stream->write(fData, fUsed);
22819382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
229fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // read from the stream, and write up to length bytes. Return the actual
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // number of bytes written.
23219382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    size_t readFromStream(SkStream* stream, size_t length) {
23319382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        return stream->read(this->reservePad(length), length);
2345595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    }
235e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com
236c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org    /**
237c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  Captures a snapshot of the data as it is right now, and return it.
238c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  Multiple calls without intervening writes may return the same SkData,
239c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  but this is not guaranteed.
240c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  Future appends will not affect the returned buffer.
241c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  It is illegal to call overwriteTAt after this without an intervening
242c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  append. It may cause the snapshot buffer to be corrupted.
243c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  Callers must unref the returned SkData.
244c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  This is not thread safe, it should only be called on the writing thread,
245c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  the result however can be shared across threads.
246c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     */
247c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org    SkData* snapshotAsData() const;
24819382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.orgprivate:
249046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    void growToAtLeast(size_t size);
2501cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
251ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    uint8_t* fData;                    // Points to either fInternal or fExternal.
252ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    size_t fCapacity;                  // Number of bytes we can write to fData.
253ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    size_t fUsed;                      // Number of bytes written.
254ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    void* fExternal;                   // Unmanaged memory block.
255ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    SkAutoTMalloc<uint8_t> fInternal;  // Managed memory block.
256c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org    SkAutoTUnref<SkData> fSnapshot;    // Holds the result of last asData.
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com/**
26051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  Helper class to allocated SIZE bytes as part of the writer, and to provide
26151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  that storage to the constructor as its initial storage buffer.
26251c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *
26351c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  This wrapper ensures proper alignment rules are met for the storage.
26451c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com */
26551c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.comtemplate <size_t SIZE> class SkSWriter32 : public SkWriter32 {
26651c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.compublic:
267a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org    SkSWriter32() { this->reset(); }
268a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org
269a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org    void reset() {this->INHERITED::reset(fData.fStorage, SIZE); }
270fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
27151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.comprivate:
27251c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    union {
27351c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        void*   fPtrAlignment;
27451c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        double  fDoubleAlignment;
27551c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        char    fStorage[SIZE];
27651c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    } fData;
277a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org
278a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org    typedef SkWriter32 INHERITED;
27951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com};
28051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
282