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
13f3c15b7cfc4eed2528f7db87ea6c1444b55ee856bungeman#include "../private/SkTemplates.h"
14c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org#include "SkData.h"
1519382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkMatrix.h"
1694e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com#include "SkPath.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPoint.h"
184ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
1919382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkRect.h"
202b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com#include "SkRegion.h"
2119382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkScalar.h"
2219382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkStream.h"
2319382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkTypes.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
253f547cb6a7fcb86d01e063b99c2d8b79d356e87fbsalomonclass SK_API 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
48046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fData = (uint8_t*)external;
49046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fCapacity = externalBytes;
50046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fUsed = 0;
51046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fExternal = external;
52ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org    }
53ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org
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);
57046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        size_t offset = fUsed;
58046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        size_t totalRequired = fUsed + size;
59046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        if (totalRequired > fCapacity) {
60a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org            this->growToAtLeast(totalRequired);
6119382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        }
62046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fUsed = totalRequired;
63046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        return (uint32_t*)(fData + offset);
6419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
65b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
66536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    /**
67536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org     *  Read a T record at offset, which must be a multiple of 4. Only legal if the record
68c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  was written atomically using the write methods below.
69536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org     */
70536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    template<typename T>
71536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    const T& readTAt(size_t offset) const {
72046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(SkAlign4(offset) == offset);
73046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(offset < fUsed);
74536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        return *(T*)(fData + offset);
75046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    }
76046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org
77536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    /**
78536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org     *  Overwrite a T record at offset, which must be a multiple of 4. Only legal if the record
79c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  was written atomically using the write methods below.
80536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org     */
81536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    template<typename T>
82536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    void overwriteTAt(size_t offset, const T& value) {
83046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(SkAlign4(offset) == offset);
84046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(offset < fUsed);
85536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        *(T*)(fData + offset) = value;
86046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    }
87a27096b4740775ae141fd0abaf456d706065c5eeskia.committer@gmail.com
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool writeBool(bool value) {
8919382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        this->write32(value);
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return value;
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
92fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeInt(int32_t value) {
9419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        this->write32(value);
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
96fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write8(int32_t value) {
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF;
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
100fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write16(int32_t value) {
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF;
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
104fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write32(int32_t value) {
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value;
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
108fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
10919382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void writePtr(void* value) {
11019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        *(void**)this->reserve(sizeof(value)) = value;
11151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    }
11251c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeScalar(SkScalar value) {
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkScalar*)this->reserve(sizeof(value)) = value;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
116fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writePoint(const SkPoint& pt) {
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkPoint*)this->reserve(sizeof(pt)) = pt;
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
120fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeRect(const SkRect& rect) {
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkRect*)this->reserve(sizeof(rect)) = rect;
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
124306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
1255587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com    void writeIRect(const SkIRect& rect) {
1265587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com        *(SkIRect*)this->reserve(sizeof(rect)) = rect;
1275587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com    }
1285587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com
1294ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    void writeRRect(const SkRRect& rrect) {
1304ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory));
1314ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
132306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
13394e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    void writePath(const SkPath& path) {
13494e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        size_t size = path.writeToMemory(NULL);
13594e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        SkASSERT(SkAlign4(size) == size);
13694e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        path.writeToMemory(this->reserve(size));
13794e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    }
13894e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com
1392b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    void writeMatrix(const SkMatrix& matrix) {
14094e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        size_t size = matrix.writeToMemory(NULL);
1412b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com        SkASSERT(SkAlign4(size) == size);
14294e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        matrix.writeToMemory(this->reserve(size));
1432b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    }
144fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1452b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    void writeRegion(const SkRegion& rgn) {
14694e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        size_t size = rgn.writeToMemory(NULL);
1472b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com        SkASSERT(SkAlign4(size) == size);
14894e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        rgn.writeToMemory(this->reserve(size));
1492b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    }
1502b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // write count bytes (must be a multiple of 4)
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeMul4(const void* values, size_t size) {
1535b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com        this->write(values, size);
1545b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    }
1555b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com
1565b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    /**
1575b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     *  Write size bytes from values. size must be a multiple of 4, though
1585b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     *  values need not be 4-byte aligned.
1595b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     */
1605b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    void write(const void* values, size_t size) {
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkAlign4(size) == size);
162e0021c0b05e78e12cd58727e770f28a45a848bb4mtklein        sk_careful_memcpy(this->reserve(size), values, size);
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
164fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1655a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com    /**
1665a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be
1675a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  filled in with zeroes.
1685a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     */
16919382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    uint32_t* reservePad(size_t size) {
170536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        size_t alignedSize = SkAlign4(size);
171536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        uint32_t* p = this->reserve(alignedSize);
172536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        if (alignedSize != size) {
173536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org            SkASSERT(alignedSize >= 4);
174536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org            p[alignedSize / 4 - 1] = 0;
17519382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        }
17619382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        return p;
17719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
1785a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com
1795a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com    /**
1805a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  Write size bytes from src, and pad to 4 byte alignment with zeroes.
1815a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     */
18219382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void writePad(const void* src, size_t size) {
183cff15aa36d750bc84bd6a48a66c9969f57476decmtklein        sk_careful_memcpy(this->reservePad(size), src, size);
18419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
185dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
186dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    /**
187dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  Writes a string to the writer, which can be retrieved with
188dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  SkReader32::readString().
189dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  The length can be specified, or if -1 is passed, it will be computed by
1900038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com     *  calling strlen(). The length must be < max size_t.
1910038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com     *
1920038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com     *  If you write NULL, it will be read as "".
193dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     */
194dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    void writeString(const char* str, size_t len = (size_t)-1);
195dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
196dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    /**
197dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  Computes the size (aligned to multiple of 4) need to write the string
198dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  in a call to writeString(). If the length is not specified, it will be
199dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  computed by calling strlen().
200dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     */
201dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    static size_t WriteStringSize(const char* str, size_t len = (size_t)-1);
202dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
203f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    void writeData(const SkData* data) {
204f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        uint32_t len = data ? SkToU32(data->size()) : 0;
205f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        this->write32(len);
206f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        if (data) {
207f70b531daaf47db1ee95c70da9843f1dd1f418d3reed            this->writePad(data->data(), len);
208f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        }
209f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
210f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
211f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    static size_t WriteDataSize(const SkData* data) {
212f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        return 4 + SkAlign4(data ? data->size() : 0);
213f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
214f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
2151cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    /**
2161cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     *  Move the cursor back to offset bytes from the beginning.
217c6d3c444ca76feba5a8937dbc80626ade5347275commit-bot@chromium.org     *  offset must be a multiple of 4 no greater than size().
2181cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     */
21919382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void rewindToOffset(size_t offset) {
22019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        SkASSERT(SkAlign4(offset) == offset);
221046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(offset <= bytesWritten());
222046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fUsed = offset;
22319382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
2241cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // copy into a single buffer (allocated by caller). Must be at least size()
22619382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void flatten(void* dst) const {
227046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        memcpy(dst, fData, fUsed);
22819382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
22919382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org
23019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    bool writeToStream(SkWStream* stream) const {
231046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        return stream->write(fData, fUsed);
23219382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
233fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // read from the stream, and write up to length bytes. Return the actual
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // number of bytes written.
23619382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    size_t readFromStream(SkStream* stream, size_t length) {
23719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        return stream->read(this->reservePad(length), length);
2385595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    }
239e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com
240c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org    /**
241c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  Captures a snapshot of the data as it is right now, and return it.
242c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     */
243fde05114e6c4107b36e1aa571c64d31def40f613reed    sk_sp<SkData> snapshotAsData() const;
24419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.orgprivate:
245046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    void growToAtLeast(size_t size);
2461cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
247ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    uint8_t* fData;                    // Points to either fInternal or fExternal.
248ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    size_t fCapacity;                  // Number of bytes we can write to fData.
249ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    size_t fUsed;                      // Number of bytes written.
250ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    void* fExternal;                   // Unmanaged memory block.
251ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    SkAutoTMalloc<uint8_t> fInternal;  // Managed memory block.
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25451c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com/**
25551c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  Helper class to allocated SIZE bytes as part of the writer, and to provide
25651c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  that storage to the constructor as its initial storage buffer.
25751c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *
25851c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  This wrapper ensures proper alignment rules are met for the storage.
25951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com */
26051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.comtemplate <size_t SIZE> class SkSWriter32 : public SkWriter32 {
26151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.compublic:
262a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org    SkSWriter32() { this->reset(); }
263a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org
264a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org    void reset() {this->INHERITED::reset(fData.fStorage, SIZE); }
265fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
26651c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.comprivate:
26751c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    union {
26851c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        void*   fPtrAlignment;
26951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        double  fDoubleAlignment;
27051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        char    fStorage[SIZE];
27151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    } fData;
272a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org
273a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org    typedef SkWriter32 INHERITED;
27451c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com};
27551c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
277