SkWriter32.h 8.8 KB

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