gfx/skia/trunk/include/core/SkWriter32.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/include/core/SkWriter32.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,281 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2008 The Android Open Source Project
     1.7 + *
     1.8 + * Use of this source code is governed by a BSD-style license that can be
     1.9 + * found in the LICENSE file.
    1.10 + */
    1.11 +
    1.12 +
    1.13 +#ifndef SkWriter32_DEFINED
    1.14 +#define SkWriter32_DEFINED
    1.15 +
    1.16 +#include "SkData.h"
    1.17 +#include "SkMatrix.h"
    1.18 +#include "SkPath.h"
    1.19 +#include "SkPoint.h"
    1.20 +#include "SkRRect.h"
    1.21 +#include "SkRect.h"
    1.22 +#include "SkRegion.h"
    1.23 +#include "SkScalar.h"
    1.24 +#include "SkStream.h"
    1.25 +#include "SkTemplates.h"
    1.26 +#include "SkTypes.h"
    1.27 +
    1.28 +class SkWriter32 : SkNoncopyable {
    1.29 +public:
    1.30 +    /**
    1.31 +     *  The caller can specify an initial block of storage, which the caller manages.
    1.32 +     *
    1.33 +     *  SkWriter32 will try to back reserve and write calls with this external storage until the
    1.34 +     *  first time an allocation doesn't fit.  From then it will use dynamically allocated storage.
    1.35 +     *  This used to be optional behavior, but pipe now relies on it.
    1.36 +     */
    1.37 +    SkWriter32(void* external = NULL, size_t externalBytes = 0) {
    1.38 +        this->reset(external, externalBytes);
    1.39 +    }
    1.40 +
    1.41 +    // return the current offset (will always be a multiple of 4)
    1.42 +    size_t bytesWritten() const { return fUsed; }
    1.43 +
    1.44 +    SK_ATTR_DEPRECATED("use bytesWritten")
    1.45 +    size_t size() const { return this->bytesWritten(); }
    1.46 +
    1.47 +    void reset(void* external = NULL, size_t externalBytes = 0) {
    1.48 +        SkASSERT(SkIsAlign4((uintptr_t)external));
    1.49 +        SkASSERT(SkIsAlign4(externalBytes));
    1.50 +
    1.51 +        fSnapshot.reset(NULL);
    1.52 +        fData = (uint8_t*)external;
    1.53 +        fCapacity = externalBytes;
    1.54 +        fUsed = 0;
    1.55 +        fExternal = external;
    1.56 +    }
    1.57 +
    1.58 +    // Returns the current buffer.
    1.59 +    // The pointer may be invalidated by any future write calls.
    1.60 +    const uint32_t* contiguousArray() const {
    1.61 +        return (uint32_t*)fData;
    1.62 +    }
    1.63 +
    1.64 +    // size MUST be multiple of 4
    1.65 +    uint32_t* reserve(size_t size) {
    1.66 +        SkASSERT(SkAlign4(size) == size);
    1.67 +        size_t offset = fUsed;
    1.68 +        size_t totalRequired = fUsed + size;
    1.69 +        if (totalRequired > fCapacity) {
    1.70 +            this->growToAtLeast(totalRequired);
    1.71 +        }
    1.72 +        fUsed = totalRequired;
    1.73 +        return (uint32_t*)(fData + offset);
    1.74 +    }
    1.75 +
    1.76 +    /**
    1.77 +     *  Read a T record at offset, which must be a multiple of 4. Only legal if the record
    1.78 +     *  was written atomically using the write methods below.
    1.79 +     */
    1.80 +    template<typename T>
    1.81 +    const T& readTAt(size_t offset) const {
    1.82 +        SkASSERT(SkAlign4(offset) == offset);
    1.83 +        SkASSERT(offset < fUsed);
    1.84 +        return *(T*)(fData + offset);
    1.85 +    }
    1.86 +
    1.87 +    /**
    1.88 +     *  Overwrite a T record at offset, which must be a multiple of 4. Only legal if the record
    1.89 +     *  was written atomically using the write methods below.
    1.90 +     */
    1.91 +    template<typename T>
    1.92 +    void overwriteTAt(size_t offset, const T& value) {
    1.93 +        SkASSERT(SkAlign4(offset) == offset);
    1.94 +        SkASSERT(offset < fUsed);
    1.95 +        SkASSERT(fSnapshot.get() == NULL);
    1.96 +        *(T*)(fData + offset) = value;
    1.97 +    }
    1.98 +
    1.99 +    bool writeBool(bool value) {
   1.100 +        this->write32(value);
   1.101 +        return value;
   1.102 +    }
   1.103 +
   1.104 +    void writeInt(int32_t value) {
   1.105 +        this->write32(value);
   1.106 +    }
   1.107 +
   1.108 +    void write8(int32_t value) {
   1.109 +        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF;
   1.110 +    }
   1.111 +
   1.112 +    void write16(int32_t value) {
   1.113 +        *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF;
   1.114 +    }
   1.115 +
   1.116 +    void write32(int32_t value) {
   1.117 +        *(int32_t*)this->reserve(sizeof(value)) = value;
   1.118 +    }
   1.119 +
   1.120 +    void writePtr(void* value) {
   1.121 +        *(void**)this->reserve(sizeof(value)) = value;
   1.122 +    }
   1.123 +
   1.124 +    void writeScalar(SkScalar value) {
   1.125 +        *(SkScalar*)this->reserve(sizeof(value)) = value;
   1.126 +    }
   1.127 +
   1.128 +    void writePoint(const SkPoint& pt) {
   1.129 +        *(SkPoint*)this->reserve(sizeof(pt)) = pt;
   1.130 +    }
   1.131 +
   1.132 +    void writeRect(const SkRect& rect) {
   1.133 +        *(SkRect*)this->reserve(sizeof(rect)) = rect;
   1.134 +    }
   1.135 +
   1.136 +    void writeIRect(const SkIRect& rect) {
   1.137 +        *(SkIRect*)this->reserve(sizeof(rect)) = rect;
   1.138 +    }
   1.139 +
   1.140 +    void writeRRect(const SkRRect& rrect) {
   1.141 +        rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory));
   1.142 +    }
   1.143 +
   1.144 +    void writePath(const SkPath& path) {
   1.145 +        size_t size = path.writeToMemory(NULL);
   1.146 +        SkASSERT(SkAlign4(size) == size);
   1.147 +        path.writeToMemory(this->reserve(size));
   1.148 +    }
   1.149 +
   1.150 +    void writeMatrix(const SkMatrix& matrix) {
   1.151 +        size_t size = matrix.writeToMemory(NULL);
   1.152 +        SkASSERT(SkAlign4(size) == size);
   1.153 +        matrix.writeToMemory(this->reserve(size));
   1.154 +    }
   1.155 +
   1.156 +    void writeRegion(const SkRegion& rgn) {
   1.157 +        size_t size = rgn.writeToMemory(NULL);
   1.158 +        SkASSERT(SkAlign4(size) == size);
   1.159 +        rgn.writeToMemory(this->reserve(size));
   1.160 +    }
   1.161 +
   1.162 +    // write count bytes (must be a multiple of 4)
   1.163 +    void writeMul4(const void* values, size_t size) {
   1.164 +        this->write(values, size);
   1.165 +    }
   1.166 +
   1.167 +    /**
   1.168 +     *  Write size bytes from values. size must be a multiple of 4, though
   1.169 +     *  values need not be 4-byte aligned.
   1.170 +     */
   1.171 +    void write(const void* values, size_t size) {
   1.172 +        SkASSERT(SkAlign4(size) == size);
   1.173 +        memcpy(this->reserve(size), values, size);
   1.174 +    }
   1.175 +
   1.176 +    /**
   1.177 +     *  Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be
   1.178 +     *  filled in with zeroes.
   1.179 +     */
   1.180 +    uint32_t* reservePad(size_t size) {
   1.181 +        size_t alignedSize = SkAlign4(size);
   1.182 +        uint32_t* p = this->reserve(alignedSize);
   1.183 +        if (alignedSize != size) {
   1.184 +            SkASSERT(alignedSize >= 4);
   1.185 +            p[alignedSize / 4 - 1] = 0;
   1.186 +        }
   1.187 +        return p;
   1.188 +    }
   1.189 +
   1.190 +    /**
   1.191 +     *  Write size bytes from src, and pad to 4 byte alignment with zeroes.
   1.192 +     */
   1.193 +    void writePad(const void* src, size_t size) {
   1.194 +        memcpy(this->reservePad(size), src, size);
   1.195 +    }
   1.196 +
   1.197 +    /**
   1.198 +     *  Writes a string to the writer, which can be retrieved with
   1.199 +     *  SkReader32::readString().
   1.200 +     *  The length can be specified, or if -1 is passed, it will be computed by
   1.201 +     *  calling strlen(). The length must be < max size_t.
   1.202 +     *
   1.203 +     *  If you write NULL, it will be read as "".
   1.204 +     */
   1.205 +    void writeString(const char* str, size_t len = (size_t)-1);
   1.206 +
   1.207 +    /**
   1.208 +     *  Computes the size (aligned to multiple of 4) need to write the string
   1.209 +     *  in a call to writeString(). If the length is not specified, it will be
   1.210 +     *  computed by calling strlen().
   1.211 +     */
   1.212 +    static size_t WriteStringSize(const char* str, size_t len = (size_t)-1);
   1.213 +
   1.214 +    /**
   1.215 +     *  Move the cursor back to offset bytes from the beginning.
   1.216 +     *  offset must be a multiple of 4 no greater than size().
   1.217 +     */
   1.218 +    void rewindToOffset(size_t offset) {
   1.219 +        SkASSERT(SkAlign4(offset) == offset);
   1.220 +        SkASSERT(offset <= bytesWritten());
   1.221 +        fUsed = offset;
   1.222 +    }
   1.223 +
   1.224 +    // copy into a single buffer (allocated by caller). Must be at least size()
   1.225 +    void flatten(void* dst) const {
   1.226 +        memcpy(dst, fData, fUsed);
   1.227 +    }
   1.228 +
   1.229 +    bool writeToStream(SkWStream* stream) const {
   1.230 +        return stream->write(fData, fUsed);
   1.231 +    }
   1.232 +
   1.233 +    // read from the stream, and write up to length bytes. Return the actual
   1.234 +    // number of bytes written.
   1.235 +    size_t readFromStream(SkStream* stream, size_t length) {
   1.236 +        return stream->read(this->reservePad(length), length);
   1.237 +    }
   1.238 +
   1.239 +    /**
   1.240 +     *  Captures a snapshot of the data as it is right now, and return it.
   1.241 +     *  Multiple calls without intervening writes may return the same SkData,
   1.242 +     *  but this is not guaranteed.
   1.243 +     *  Future appends will not affect the returned buffer.
   1.244 +     *  It is illegal to call overwriteTAt after this without an intervening
   1.245 +     *  append. It may cause the snapshot buffer to be corrupted.
   1.246 +     *  Callers must unref the returned SkData.
   1.247 +     *  This is not thread safe, it should only be called on the writing thread,
   1.248 +     *  the result however can be shared across threads.
   1.249 +     */
   1.250 +    SkData* snapshotAsData() const;
   1.251 +private:
   1.252 +    void growToAtLeast(size_t size);
   1.253 +
   1.254 +    uint8_t* fData;                    // Points to either fInternal or fExternal.
   1.255 +    size_t fCapacity;                  // Number of bytes we can write to fData.
   1.256 +    size_t fUsed;                      // Number of bytes written.
   1.257 +    void* fExternal;                   // Unmanaged memory block.
   1.258 +    SkAutoTMalloc<uint8_t> fInternal;  // Managed memory block.
   1.259 +    SkAutoTUnref<SkData> fSnapshot;    // Holds the result of last asData.
   1.260 +};
   1.261 +
   1.262 +/**
   1.263 + *  Helper class to allocated SIZE bytes as part of the writer, and to provide
   1.264 + *  that storage to the constructor as its initial storage buffer.
   1.265 + *
   1.266 + *  This wrapper ensures proper alignment rules are met for the storage.
   1.267 + */
   1.268 +template <size_t SIZE> class SkSWriter32 : public SkWriter32 {
   1.269 +public:
   1.270 +    SkSWriter32() { this->reset(); }
   1.271 +
   1.272 +    void reset() {this->INHERITED::reset(fData.fStorage, SIZE); }
   1.273 +
   1.274 +private:
   1.275 +    union {
   1.276 +        void*   fPtrAlignment;
   1.277 +        double  fDoubleAlignment;
   1.278 +        char    fStorage[SIZE];
   1.279 +    } fData;
   1.280 +
   1.281 +    typedef SkWriter32 INHERITED;
   1.282 +};
   1.283 +
   1.284 +#endif

mercurial