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"
184123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth#include "SkPoint3.h"
194ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
2019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkRect.h"
212b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com#include "SkRegion.h"
2219382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkScalar.h"
2319382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkStream.h"
2419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkTypes.h"
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
263f547cb6a7fcb86d01e063b99c2d8b79d356e87fbsalomonclass SK_API SkWriter32 : SkNoncopyable {
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
28e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com    /**
29e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com     *  The caller can specify an initial block of storage, which the caller manages.
3019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org     *
3119382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org     *  SkWriter32 will try to back reserve and write calls with this external storage until the
3219382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org     *  first time an allocation doesn't fit.  From then it will use dynamically allocated storage.
3319382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org     *  This used to be optional behavior, but pipe now relies on it.
34e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com     */
35a93a14a99816d25b773f0b12868143702baf44bfBen Wagner    SkWriter32(void* external = nullptr, size_t externalBytes = 0) {
3619382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        this->reset(external, externalBytes);
3719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
391cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    // return the current offset (will always be a multiple of 4)
40046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    size_t bytesWritten() const { return fUsed; }
414469938e92d779dff05e745559e67907bbf21e78reed@google.com
424469938e92d779dff05e745559e67907bbf21e78reed@google.com    SK_ATTR_DEPRECATED("use bytesWritten")
43adacc7067ad617cdc7bbef39192ca80f4b4d27f9robertphillips@google.com    size_t size() const { return this->bytesWritten(); }
441cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
45a93a14a99816d25b773f0b12868143702baf44bfBen Wagner    void reset(void* external = nullptr, size_t externalBytes = 0) {
4619382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        SkASSERT(SkIsAlign4((uintptr_t)external));
4719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        SkASSERT(SkIsAlign4(externalBytes));
48046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org
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
555595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    // size MUST be multiple of 4
565595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    uint32_t* reserve(size_t size) {
575595af1b2ebe6590e98641464d43d22281a7f295reed@google.com        SkASSERT(SkAlign4(size) == size);
58046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        size_t offset = fUsed;
59046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        size_t totalRequired = fUsed + size;
60046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        if (totalRequired > fCapacity) {
61a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org            this->growToAtLeast(totalRequired);
6219382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        }
63046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fUsed = totalRequired;
64046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        return (uint32_t*)(fData + offset);
6519382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
66b89a03c890668f98d9f8b269b6ad00824409435bskia.committer@gmail.com
67536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    /**
68536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org     *  Read a T record at offset, which must be a multiple of 4. Only legal if the record
69c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  was written atomically using the write methods below.
70536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org     */
71536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    template<typename T>
72536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    const T& readTAt(size_t offset) const {
73046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(SkAlign4(offset) == offset);
74046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(offset < fUsed);
75536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        return *(T*)(fData + offset);
76046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    }
77046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org
78536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    /**
79536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org     *  Overwrite a T record at offset, which must be a multiple of 4. Only legal if the record
80c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  was written atomically using the write methods below.
81536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org     */
82536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    template<typename T>
83536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    void overwriteTAt(size_t offset, const T& value) {
84046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(SkAlign4(offset) == offset);
85046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(offset < fUsed);
86536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        *(T*)(fData + offset) = value;
87046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    }
88a27096b4740775ae141fd0abaf456d706065c5eeskia.committer@gmail.com
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool writeBool(bool value) {
9019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        this->write32(value);
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return value;
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
93fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeInt(int32_t value) {
9519382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        this->write32(value);
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
97fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write8(int32_t value) {
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF;
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
101fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write16(int32_t value) {
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF;
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
105fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void write32(int32_t value) {
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(int32_t*)this->reserve(sizeof(value)) = value;
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
109fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
11019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void writePtr(void* value) {
11119382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        *(void**)this->reserve(sizeof(value)) = value;
11251c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    }
11351c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeScalar(SkScalar value) {
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkScalar*)this->reserve(sizeof(value)) = value;
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
117fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writePoint(const SkPoint& pt) {
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkPoint*)this->reserve(sizeof(pt)) = pt;
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
121fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1224123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    void writePoint3(const SkPoint3& pt) {
1234123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth        *(SkPoint3*)this->reserve(sizeof(pt)) = pt;
1244123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth    }
1254123d0ff867f41c40fd288b31f4c976069753cccJim Van Verth
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeRect(const SkRect& rect) {
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *(SkRect*)this->reserve(sizeof(rect)) = rect;
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
129306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
1305587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com    void writeIRect(const SkIRect& rect) {
1315587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com        *(SkIRect*)this->reserve(sizeof(rect)) = rect;
1325587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com    }
1335587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com
1344ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    void writeRRect(const SkRRect& rrect) {
1354ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory));
1364ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
137306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
13894e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    void writePath(const SkPath& path) {
139a93a14a99816d25b773f0b12868143702baf44bfBen Wagner        size_t size = path.writeToMemory(nullptr);
14094e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        SkASSERT(SkAlign4(size) == size);
14194e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        path.writeToMemory(this->reserve(size));
14294e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    }
14394e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com
1446d6d603c812a6c9bb3e70157be909d355233ba6dCary Clark    void writeMatrix(const SkMatrix& matrix);
145fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1462b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    void writeRegion(const SkRegion& rgn) {
147a93a14a99816d25b773f0b12868143702baf44bfBen Wagner        size_t size = rgn.writeToMemory(nullptr);
1482b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com        SkASSERT(SkAlign4(size) == size);
14994e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com        rgn.writeToMemory(this->reserve(size));
1502b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    }
1512b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // write count bytes (must be a multiple of 4)
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void writeMul4(const void* values, size_t size) {
1545b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com        this->write(values, size);
1555b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    }
1565b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com
1575b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    /**
1585b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     *  Write size bytes from values. size must be a multiple of 4, though
1595b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     *  values need not be 4-byte aligned.
1605b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com     */
1615b3d5349bedf37ec6fcf03bac04cf33129fc176areed@google.com    void write(const void* values, size_t size) {
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkAlign4(size) == size);
163e0021c0b05e78e12cd58727e770f28a45a848bb4mtklein        sk_careful_memcpy(this->reserve(size), values, size);
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
165fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1665a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com    /**
1675a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be
1685a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  filled in with zeroes.
1695a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     */
17019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    uint32_t* reservePad(size_t size) {
171536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        size_t alignedSize = SkAlign4(size);
172536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        uint32_t* p = this->reserve(alignedSize);
173536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org        if (alignedSize != size) {
174536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org            SkASSERT(alignedSize >= 4);
175536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org            p[alignedSize / 4 - 1] = 0;
17619382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        }
17719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        return p;
17819382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
1795a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com
1805a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com    /**
1815a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     *  Write size bytes from src, and pad to 4 byte alignment with zeroes.
1825a7c6be72b940dde8ff6ad2485a09aecd56a2660scroggo@google.com     */
18319382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void writePad(const void* src, size_t size) {
184cff15aa36d750bc84bd6a48a66c9969f57476decmtklein        sk_careful_memcpy(this->reservePad(size), src, size);
18519382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
186dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
187dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    /**
188dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  Writes a string to the writer, which can be retrieved with
189dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  SkReader32::readString().
190dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  The length can be specified, or if -1 is passed, it will be computed by
1910038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com     *  calling strlen(). The length must be < max size_t.
1920038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com     *
1930038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com     *  If you write NULL, it will be read as "".
194dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     */
195dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    void writeString(const char* str, size_t len = (size_t)-1);
196dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
197dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    /**
198dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  Computes the size (aligned to multiple of 4) need to write the string
199dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  in a call to writeString(). If the length is not specified, it will be
200dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     *  computed by calling strlen().
201dde0956375e87027df2fdd80d430dd819c217aacreed@google.com     */
202dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    static size_t WriteStringSize(const char* str, size_t len = (size_t)-1);
203dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
204f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    void writeData(const SkData* data) {
205f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        uint32_t len = data ? SkToU32(data->size()) : 0;
206f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        this->write32(len);
207f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        if (data) {
208f70b531daaf47db1ee95c70da9843f1dd1f418d3reed            this->writePad(data->data(), len);
209f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        }
210f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
211f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
212f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    static size_t WriteDataSize(const SkData* data) {
213f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        return 4 + SkAlign4(data ? data->size() : 0);
214f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
215f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
2161cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com    /**
2171cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     *  Move the cursor back to offset bytes from the beginning.
218c6d3c444ca76feba5a8937dbc80626ade5347275commit-bot@chromium.org     *  offset must be a multiple of 4 no greater than size().
2191cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com     */
22019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void rewindToOffset(size_t offset) {
22119382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        SkASSERT(SkAlign4(offset) == offset);
222046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        SkASSERT(offset <= bytesWritten());
223046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        fUsed = offset;
22419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
2251cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // copy into a single buffer (allocated by caller). Must be at least size()
22719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    void flatten(void* dst) const {
228046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        memcpy(dst, fData, fUsed);
22919382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
23019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org
23119382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    bool writeToStream(SkWStream* stream) const {
232046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        return stream->write(fData, fUsed);
23319382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    }
234fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // read from the stream, and write up to length bytes. Return the actual
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // number of bytes written.
23719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    size_t readFromStream(SkStream* stream, size_t length) {
23819382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org        return stream->read(this->reservePad(length), length);
2395595af1b2ebe6590e98641464d43d22281a7f295reed@google.com    }
240e49aca968ca27d90ca919a972a86839ecaf1224areed@google.com
241c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org    /**
242c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     *  Captures a snapshot of the data as it is right now, and return it.
243c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org     */
244fde05114e6c4107b36e1aa571c64d31def40f613reed    sk_sp<SkData> snapshotAsData() const;
24519382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.orgprivate:
246046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    void growToAtLeast(size_t size);
2471cf58d03a87e1ff17cd47e9de3da4c678456618dreed@google.com
248ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    uint8_t* fData;                    // Points to either fInternal or fExternal.
249ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    size_t fCapacity;                  // Number of bytes we can write to fData.
250ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    size_t fUsed;                      // Number of bytes written.
251ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    void* fExternal;                   // Unmanaged memory block.
252ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    SkAutoTMalloc<uint8_t> fInternal;  // Managed memory block.
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25551c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com/**
25651c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  Helper class to allocated SIZE bytes as part of the writer, and to provide
25751c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  that storage to the constructor as its initial storage buffer.
25851c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *
25951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com *  This wrapper ensures proper alignment rules are met for the storage.
26051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com */
26151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.comtemplate <size_t SIZE> class SkSWriter32 : public SkWriter32 {
26251c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.compublic:
263a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org    SkSWriter32() { this->reset(); }
264a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org
265a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org    void reset() {this->INHERITED::reset(fData.fStorage, SIZE); }
266fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
26751c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.comprivate:
26851c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    union {
26951c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        void*   fPtrAlignment;
27051c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        double  fDoubleAlignment;
27151c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com        char    fStorage[SIZE];
27251c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com    } fData;
273a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org
274a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org    typedef SkWriter32 INHERITED;
27551c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com};
27651c62a6cfadc302bb65bb5a98e358c93223dc73freed@google.com
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
278