1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2008 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#ifndef SkWriter32_DEFINED 9cb93a386Sopenharmony_ci#define SkWriter32_DEFINED 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "include/core/SkData.h" 12cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h" 13cb93a386Sopenharmony_ci#include "include/core/SkPath.h" 14cb93a386Sopenharmony_ci#include "include/core/SkPoint.h" 15cb93a386Sopenharmony_ci#include "include/core/SkPoint3.h" 16cb93a386Sopenharmony_ci#include "include/core/SkRRect.h" 17cb93a386Sopenharmony_ci#include "include/core/SkRect.h" 18cb93a386Sopenharmony_ci#include "include/core/SkRegion.h" 19cb93a386Sopenharmony_ci#include "include/core/SkScalar.h" 20cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 21cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 22cb93a386Sopenharmony_ci#include "include/private/SkNoncopyable.h" 23cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h" 24cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ciclass SK_API SkWriter32 : SkNoncopyable { 27cb93a386Sopenharmony_cipublic: 28cb93a386Sopenharmony_ci /** 29cb93a386Sopenharmony_ci * The caller can specify an initial block of storage, which the caller manages. 30cb93a386Sopenharmony_ci * 31cb93a386Sopenharmony_ci * SkWriter32 will try to back reserve and write calls with this external storage until the 32cb93a386Sopenharmony_ci * first time an allocation doesn't fit. From then it will use dynamically allocated storage. 33cb93a386Sopenharmony_ci * This used to be optional behavior, but pipe now relies on it. 34cb93a386Sopenharmony_ci */ 35cb93a386Sopenharmony_ci SkWriter32(void* external = nullptr, size_t externalBytes = 0) { 36cb93a386Sopenharmony_ci this->reset(external, externalBytes); 37cb93a386Sopenharmony_ci } 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci // return the current offset (will always be a multiple of 4) 40cb93a386Sopenharmony_ci size_t bytesWritten() const { return fUsed; } 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci // Returns true iff all of the bytes written so far are stored in the initial storage 43cb93a386Sopenharmony_ci // buffer provided in the constructor or the most recent call to reset. 44cb93a386Sopenharmony_ci bool usingInitialStorage() const { return fData == fExternal; } 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ci void reset(void* external = nullptr, size_t externalBytes = 0) { 47cb93a386Sopenharmony_ci // we cast this pointer to int* and float* at times, so assert that it is aligned. 48cb93a386Sopenharmony_ci SkASSERT(SkIsAlign4((uintptr_t)external)); 49cb93a386Sopenharmony_ci // we always write multiples of 4-bytes, so truncate down the size to match that 50cb93a386Sopenharmony_ci externalBytes &= ~3; 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci fData = (uint8_t*)external; 53cb93a386Sopenharmony_ci fCapacity = externalBytes; 54cb93a386Sopenharmony_ci fUsed = 0; 55cb93a386Sopenharmony_ci fExternal = external; 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci // size MUST be multiple of 4 59cb93a386Sopenharmony_ci uint32_t* reserve(size_t size) { 60cb93a386Sopenharmony_ci SkASSERT(SkAlign4(size) == size); 61cb93a386Sopenharmony_ci size_t offset = fUsed; 62cb93a386Sopenharmony_ci size_t totalRequired = fUsed + size; 63cb93a386Sopenharmony_ci if (totalRequired > fCapacity) { 64cb93a386Sopenharmony_ci this->growToAtLeast(totalRequired); 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci fUsed = totalRequired; 67cb93a386Sopenharmony_ci return (uint32_t*)(fData + offset); 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ci /** 71cb93a386Sopenharmony_ci * Read a T record at offset, which must be a multiple of 4. Only legal if the record 72cb93a386Sopenharmony_ci * was written atomically using the write methods below. 73cb93a386Sopenharmony_ci */ 74cb93a386Sopenharmony_ci template<typename T> 75cb93a386Sopenharmony_ci const T& readTAt(size_t offset) const { 76cb93a386Sopenharmony_ci SkASSERT(SkAlign4(offset) == offset); 77cb93a386Sopenharmony_ci SkASSERT(offset < fUsed); 78cb93a386Sopenharmony_ci return *(T*)(fData + offset); 79cb93a386Sopenharmony_ci } 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci /** 82cb93a386Sopenharmony_ci * Overwrite a T record at offset, which must be a multiple of 4. Only legal if the record 83cb93a386Sopenharmony_ci * was written atomically using the write methods below. 84cb93a386Sopenharmony_ci */ 85cb93a386Sopenharmony_ci template<typename T> 86cb93a386Sopenharmony_ci void overwriteTAt(size_t offset, const T& value) { 87cb93a386Sopenharmony_ci SkASSERT(SkAlign4(offset) == offset); 88cb93a386Sopenharmony_ci SkASSERT(offset < fUsed); 89cb93a386Sopenharmony_ci *(T*)(fData + offset) = value; 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_ci bool writeBool(bool value) { 93cb93a386Sopenharmony_ci this->write32(value); 94cb93a386Sopenharmony_ci return value; 95cb93a386Sopenharmony_ci } 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci void writeInt(int32_t value) { 98cb93a386Sopenharmony_ci this->write32(value); 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci void write8(int32_t value) { 102cb93a386Sopenharmony_ci *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF; 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci void write16(int32_t value) { 106cb93a386Sopenharmony_ci *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF; 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ci void write32(int32_t value) { 110cb93a386Sopenharmony_ci *(int32_t*)this->reserve(sizeof(value)) = value; 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci void writeScalar(SkScalar value) { 114cb93a386Sopenharmony_ci *(SkScalar*)this->reserve(sizeof(value)) = value; 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci void writePoint(const SkPoint& pt) { 118cb93a386Sopenharmony_ci *(SkPoint*)this->reserve(sizeof(pt)) = pt; 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci void writePoint3(const SkPoint3& pt) { 122cb93a386Sopenharmony_ci *(SkPoint3*)this->reserve(sizeof(pt)) = pt; 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci void writeRect(const SkRect& rect) { 126cb93a386Sopenharmony_ci *(SkRect*)this->reserve(sizeof(rect)) = rect; 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci void writeIRect(const SkIRect& rect) { 130cb93a386Sopenharmony_ci *(SkIRect*)this->reserve(sizeof(rect)) = rect; 131cb93a386Sopenharmony_ci } 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_ci void writeRRect(const SkRRect& rrect) { 134cb93a386Sopenharmony_ci rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory)); 135cb93a386Sopenharmony_ci } 136cb93a386Sopenharmony_ci 137cb93a386Sopenharmony_ci void writePath(const SkPath& path) { 138cb93a386Sopenharmony_ci size_t size = path.writeToMemory(nullptr); 139cb93a386Sopenharmony_ci SkASSERT(SkAlign4(size) == size); 140cb93a386Sopenharmony_ci path.writeToMemory(this->reserve(size)); 141cb93a386Sopenharmony_ci } 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci void writeMatrix(const SkMatrix& matrix); 144cb93a386Sopenharmony_ci 145cb93a386Sopenharmony_ci void writeRegion(const SkRegion& rgn) { 146cb93a386Sopenharmony_ci size_t size = rgn.writeToMemory(nullptr); 147cb93a386Sopenharmony_ci SkASSERT(SkAlign4(size) == size); 148cb93a386Sopenharmony_ci rgn.writeToMemory(this->reserve(size)); 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci // write count bytes (must be a multiple of 4) 152cb93a386Sopenharmony_ci void writeMul4(const void* values, size_t size) { 153cb93a386Sopenharmony_ci this->write(values, size); 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ci /** 157cb93a386Sopenharmony_ci * Write size bytes from values. size must be a multiple of 4, though 158cb93a386Sopenharmony_ci * values need not be 4-byte aligned. 159cb93a386Sopenharmony_ci */ 160cb93a386Sopenharmony_ci void write(const void* values, size_t size) { 161cb93a386Sopenharmony_ci SkASSERT(SkAlign4(size) == size); 162cb93a386Sopenharmony_ci sk_careful_memcpy(this->reserve(size), values, size); 163cb93a386Sopenharmony_ci } 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ci /** 166cb93a386Sopenharmony_ci * Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be 167cb93a386Sopenharmony_ci * filled in with zeroes. 168cb93a386Sopenharmony_ci */ 169cb93a386Sopenharmony_ci uint32_t* reservePad(size_t size) { 170cb93a386Sopenharmony_ci size_t alignedSize = SkAlign4(size); 171cb93a386Sopenharmony_ci uint32_t* p = this->reserve(alignedSize); 172cb93a386Sopenharmony_ci if (alignedSize != size) { 173cb93a386Sopenharmony_ci SkASSERT(alignedSize >= 4); 174cb93a386Sopenharmony_ci p[alignedSize / 4 - 1] = 0; 175cb93a386Sopenharmony_ci } 176cb93a386Sopenharmony_ci return p; 177cb93a386Sopenharmony_ci } 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ci /** 180cb93a386Sopenharmony_ci * Write size bytes from src, and pad to 4 byte alignment with zeroes. 181cb93a386Sopenharmony_ci */ 182cb93a386Sopenharmony_ci void writePad(const void* src, size_t size) { 183cb93a386Sopenharmony_ci sk_careful_memcpy(this->reservePad(size), src, size); 184cb93a386Sopenharmony_ci } 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_ci /** 187cb93a386Sopenharmony_ci * Writes a string to the writer, which can be retrieved with SkReadBuffer::readString(). 188cb93a386Sopenharmony_ci * The length can be specified, or if -1 is passed, it will be computed by calling strlen(). 189cb93a386Sopenharmony_ci * The length must be < max size_t. 190cb93a386Sopenharmony_ci * 191cb93a386Sopenharmony_ci * If you write NULL, it will be read as "". 192cb93a386Sopenharmony_ci */ 193cb93a386Sopenharmony_ci void writeString(const char* str, size_t len = (size_t)-1); 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ci /** 196cb93a386Sopenharmony_ci * Computes the size (aligned to multiple of 4) need to write the string 197cb93a386Sopenharmony_ci * in a call to writeString(). If the length is not specified, it will be 198cb93a386Sopenharmony_ci * computed by calling strlen(). 199cb93a386Sopenharmony_ci */ 200cb93a386Sopenharmony_ci static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); 201cb93a386Sopenharmony_ci 202cb93a386Sopenharmony_ci void writeData(const SkData* data) { 203cb93a386Sopenharmony_ci uint32_t len = data ? SkToU32(data->size()) : 0; 204cb93a386Sopenharmony_ci this->write32(len); 205cb93a386Sopenharmony_ci if (data) { 206cb93a386Sopenharmony_ci this->writePad(data->data(), len); 207cb93a386Sopenharmony_ci } 208cb93a386Sopenharmony_ci } 209cb93a386Sopenharmony_ci 210cb93a386Sopenharmony_ci static size_t WriteDataSize(const SkData* data) { 211cb93a386Sopenharmony_ci return 4 + SkAlign4(data ? data->size() : 0); 212cb93a386Sopenharmony_ci } 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_ci /** 215cb93a386Sopenharmony_ci * Move the cursor back to offset bytes from the beginning. 216cb93a386Sopenharmony_ci * offset must be a multiple of 4 no greater than size(). 217cb93a386Sopenharmony_ci */ 218cb93a386Sopenharmony_ci void rewindToOffset(size_t offset) { 219cb93a386Sopenharmony_ci SkASSERT(SkAlign4(offset) == offset); 220cb93a386Sopenharmony_ci SkASSERT(offset <= bytesWritten()); 221cb93a386Sopenharmony_ci fUsed = offset; 222cb93a386Sopenharmony_ci } 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ci // copy into a single buffer (allocated by caller). Must be at least size() 225cb93a386Sopenharmony_ci void flatten(void* dst) const { 226cb93a386Sopenharmony_ci memcpy(dst, fData, fUsed); 227cb93a386Sopenharmony_ci } 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_ci bool writeToStream(SkWStream* stream) const { 230cb93a386Sopenharmony_ci return stream->write(fData, fUsed); 231cb93a386Sopenharmony_ci } 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_ci // read from the stream, and write up to length bytes. Return the actual 234cb93a386Sopenharmony_ci // number of bytes written. 235cb93a386Sopenharmony_ci size_t readFromStream(SkStream* stream, size_t length) { 236cb93a386Sopenharmony_ci return stream->read(this->reservePad(length), length); 237cb93a386Sopenharmony_ci } 238cb93a386Sopenharmony_ci 239cb93a386Sopenharmony_ci /** 240cb93a386Sopenharmony_ci * Captures a snapshot of the data as it is right now, and return it. 241cb93a386Sopenharmony_ci */ 242cb93a386Sopenharmony_ci sk_sp<SkData> snapshotAsData() const; 243cb93a386Sopenharmony_ciprivate: 244cb93a386Sopenharmony_ci void growToAtLeast(size_t size); 245cb93a386Sopenharmony_ci 246cb93a386Sopenharmony_ci uint8_t* fData; // Points to either fInternal or fExternal. 247cb93a386Sopenharmony_ci size_t fCapacity; // Number of bytes we can write to fData. 248cb93a386Sopenharmony_ci size_t fUsed; // Number of bytes written. 249cb93a386Sopenharmony_ci void* fExternal; // Unmanaged memory block. 250cb93a386Sopenharmony_ci SkAutoTMalloc<uint8_t> fInternal; // Managed memory block. 251cb93a386Sopenharmony_ci}; 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_ci/** 254cb93a386Sopenharmony_ci * Helper class to allocated SIZE bytes as part of the writer, and to provide 255cb93a386Sopenharmony_ci * that storage to the constructor as its initial storage buffer. 256cb93a386Sopenharmony_ci * 257cb93a386Sopenharmony_ci * This wrapper ensures proper alignment rules are met for the storage. 258cb93a386Sopenharmony_ci */ 259cb93a386Sopenharmony_citemplate <size_t SIZE> class SkSWriter32 : public SkWriter32 { 260cb93a386Sopenharmony_cipublic: 261cb93a386Sopenharmony_ci SkSWriter32() { this->reset(); } 262cb93a386Sopenharmony_ci 263cb93a386Sopenharmony_ci void reset() {this->INHERITED::reset(fData.fStorage, SIZE); } 264cb93a386Sopenharmony_ci 265cb93a386Sopenharmony_ciprivate: 266cb93a386Sopenharmony_ci union { 267cb93a386Sopenharmony_ci void* fPtrAlignment; 268cb93a386Sopenharmony_ci double fDoubleAlignment; 269cb93a386Sopenharmony_ci char fStorage[SIZE]; 270cb93a386Sopenharmony_ci } fData; 271cb93a386Sopenharmony_ci 272cb93a386Sopenharmony_ci using INHERITED = SkWriter32; 273cb93a386Sopenharmony_ci}; 274cb93a386Sopenharmony_ci 275cb93a386Sopenharmony_ci#endif 276