SkVertices.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. * Copyright 2017 Google Inc.
  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 SkVertices_DEFINED
  8. #define SkVertices_DEFINED
  9. #include "include/core/SkColor.h"
  10. #include "include/core/SkData.h"
  11. #include "include/core/SkPoint.h"
  12. #include "include/core/SkRect.h"
  13. #include "include/core/SkRefCnt.h"
  14. /**
  15. * An immutable set of vertex data that can be used with SkCanvas::drawVertices.
  16. */
  17. class SK_API SkVertices : public SkNVRefCnt<SkVertices> {
  18. public:
  19. // BoneIndices indicates which (of a maximum of 4 bones) a given vertex will interpolate
  20. // between. To indicate that a slot is not used, the convention is to assign the bone index
  21. // to 0.
  22. struct BoneIndices {
  23. uint32_t indices[4];
  24. uint32_t& operator[] (int i) {
  25. SkASSERT(i >= 0);
  26. SkASSERT(i < 4);
  27. return indices[i];
  28. }
  29. const uint32_t& operator[] (int i) const {
  30. SkASSERT(i >= 0);
  31. SkASSERT(i < 4);
  32. return indices[i];
  33. }
  34. };
  35. // BoneWeights stores the interpolation weight for each of the (maximum of 4) bones a given
  36. // vertex interpolates between. To indicate that a slot is not used, the weight for that
  37. // slot should be 0.
  38. struct BoneWeights {
  39. float weights[4];
  40. float& operator[] (int i) {
  41. SkASSERT(i >= 0);
  42. SkASSERT(i < 4);
  43. return weights[i];
  44. }
  45. const float& operator[] (int i) const {
  46. SkASSERT(i >= 0);
  47. SkASSERT(i < 4);
  48. return weights[i];
  49. }
  50. };
  51. // Bone stores a 3x2 transformation matrix in column major order:
  52. // | scaleX skewX transX |
  53. // | skewY scaleY transY |
  54. // SkRSXform is insufficient because bones can have non uniform scale.
  55. struct Bone {
  56. float values[6];
  57. float& operator[] (int i) {
  58. SkASSERT(i >= 0);
  59. SkASSERT(i < 6);
  60. return values[i];
  61. }
  62. const float& operator[] (int i) const {
  63. SkASSERT(i >= 0);
  64. SkASSERT(i < 6);
  65. return values[i];
  66. }
  67. SkPoint mapPoint(const SkPoint& point) const {
  68. float x = values[0] * point.x() + values[2] * point.y() + values[4];
  69. float y = values[1] * point.x() + values[3] * point.y() + values[5];
  70. return SkPoint::Make(x, y);
  71. }
  72. SkRect mapRect(const SkRect& rect) const {
  73. SkRect dst = SkRect::MakeEmpty();
  74. SkPoint quad[4];
  75. rect.toQuad(quad);
  76. for (int i = 0; i < 4; i ++) {
  77. quad[i] = mapPoint(quad[i]);
  78. }
  79. dst.setBoundsNoCheck(quad, 4);
  80. return dst;
  81. }
  82. };
  83. enum VertexMode {
  84. kTriangles_VertexMode,
  85. kTriangleStrip_VertexMode,
  86. kTriangleFan_VertexMode,
  87. kLast_VertexMode = kTriangleFan_VertexMode,
  88. };
  89. /**
  90. * Create a vertices by copying the specified arrays. texs, colors, boneIndices, and
  91. * boneWeights may be nullptr, and indices is ignored if indexCount == 0.
  92. *
  93. * boneIndices and boneWeights must either both be nullptr or both point to valid data.
  94. * If specified, they must both contain 'vertexCount' entries.
  95. */
  96. static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
  97. const SkPoint positions[],
  98. const SkPoint texs[],
  99. const SkColor colors[],
  100. const BoneIndices boneIndices[],
  101. const BoneWeights boneWeights[],
  102. int indexCount,
  103. const uint16_t indices[],
  104. bool isVolatile = true);
  105. static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
  106. const SkPoint positions[],
  107. const SkPoint texs[],
  108. const SkColor colors[],
  109. const BoneIndices boneIndices[],
  110. const BoneWeights boneWeights[],
  111. bool isVolatile = true) {
  112. return MakeCopy(mode,
  113. vertexCount,
  114. positions,
  115. texs,
  116. colors,
  117. boneIndices,
  118. boneWeights,
  119. 0,
  120. nullptr,
  121. isVolatile);
  122. }
  123. static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
  124. const SkPoint positions[],
  125. const SkPoint texs[],
  126. const SkColor colors[],
  127. int indexCount,
  128. const uint16_t indices[],
  129. bool isVolatile = true) {
  130. return MakeCopy(mode,
  131. vertexCount,
  132. positions,
  133. texs,
  134. colors,
  135. nullptr,
  136. nullptr,
  137. indexCount,
  138. indices,
  139. isVolatile);
  140. }
  141. static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
  142. const SkPoint positions[],
  143. const SkPoint texs[],
  144. const SkColor colors[],
  145. bool isVolatile = true) {
  146. return MakeCopy(mode, vertexCount, positions, texs, colors, nullptr, nullptr, isVolatile);
  147. }
  148. struct Sizes;
  149. enum BuilderFlags {
  150. kHasTexCoords_BuilderFlag = 1 << 0,
  151. kHasColors_BuilderFlag = 1 << 1,
  152. kHasBones_BuilderFlag = 1 << 2,
  153. kIsNonVolatile_BuilderFlag = 1 << 3,
  154. };
  155. class Builder {
  156. public:
  157. Builder(VertexMode mode, int vertexCount, int indexCount, uint32_t flags);
  158. bool isValid() const { return fVertices != nullptr; }
  159. // if the builder is invalid, these will return 0
  160. int vertexCount() const;
  161. int indexCount() const;
  162. bool isVolatile() const;
  163. SkPoint* positions();
  164. SkPoint* texCoords(); // returns null if there are no texCoords
  165. SkColor* colors(); // returns null if there are no colors
  166. BoneIndices* boneIndices(); // returns null if there are no bone indices
  167. BoneWeights* boneWeights(); // returns null if there are no bone weights
  168. uint16_t* indices(); // returns null if there are no indices
  169. // Detach the built vertices object. After the first call, this will always return null.
  170. sk_sp<SkVertices> detach();
  171. private:
  172. Builder(VertexMode mode, int vertexCount, int indexCount, bool isVolatile, const Sizes&);
  173. void init(VertexMode mode, int vertexCount, int indexCount, bool isVolatile, const Sizes&);
  174. // holds a partially complete object. only completed in detach()
  175. sk_sp<SkVertices> fVertices;
  176. // Extra storage for intermediate vertices in the case where the client specifies indexed
  177. // triangle fans. These get converted to indexed triangles when the Builder is finalized.
  178. std::unique_ptr<uint8_t[]> fIntermediateFanIndices;
  179. friend class SkVertices;
  180. };
  181. uint32_t uniqueID() const { return fUniqueID; }
  182. VertexMode mode() const { return fMode; }
  183. const SkRect& bounds() const { return fBounds; }
  184. bool hasColors() const { return SkToBool(this->colors()); }
  185. bool hasTexCoords() const { return SkToBool(this->texCoords()); }
  186. bool hasBones() const { return SkToBool(this->boneIndices()); }
  187. bool hasIndices() const { return SkToBool(this->indices()); }
  188. int vertexCount() const { return fVertexCnt; }
  189. const SkPoint* positions() const { return fPositions; }
  190. const SkPoint* texCoords() const { return fTexs; }
  191. const SkColor* colors() const { return fColors; }
  192. const BoneIndices* boneIndices() const { return fBoneIndices; }
  193. const BoneWeights* boneWeights() const { return fBoneWeights; }
  194. int indexCount() const { return fIndexCnt; }
  195. const uint16_t* indices() const { return fIndices; }
  196. bool isVolatile() const { return fIsVolatile; }
  197. sk_sp<SkVertices> applyBones(const Bone bones[], int boneCount) const;
  198. // returns approximate byte size of the vertices object
  199. size_t approximateSize() const;
  200. /**
  201. * Recreate a vertices from a buffer previously created by calling encode().
  202. * Returns null if the data is corrupt or the length is incorrect for the contents.
  203. */
  204. static sk_sp<SkVertices> Decode(const void* buffer, size_t length);
  205. /**
  206. * Pack the vertices object into a byte buffer. This can be used to recreate the vertices
  207. * by calling Decode() with the buffer.
  208. */
  209. sk_sp<SkData> encode() const;
  210. private:
  211. SkVertices() {}
  212. // these are needed since we've manually sized our allocation (see Builder::init)
  213. friend class SkNVRefCnt<SkVertices>;
  214. void operator delete(void* p);
  215. static sk_sp<SkVertices> Alloc(int vCount, int iCount, uint32_t builderFlags,
  216. size_t* arraySize);
  217. // we store this first, to pair with the refcnt in our base-class, so we don't have an
  218. // unnecessary pad between it and the (possibly 8-byte aligned) ptrs.
  219. uint32_t fUniqueID;
  220. // these point inside our allocation, so none of these can be "freed"
  221. SkPoint* fPositions;
  222. SkPoint* fTexs;
  223. SkColor* fColors;
  224. BoneIndices* fBoneIndices;
  225. BoneWeights* fBoneWeights;
  226. uint16_t* fIndices;
  227. SkRect fBounds; // computed to be the union of the fPositions[]
  228. int fVertexCnt;
  229. int fIndexCnt;
  230. bool fIsVolatile;
  231. VertexMode fMode;
  232. // below here is where the actual array data is stored.
  233. };
  234. #endif