123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- /*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #ifndef SkVertices_DEFINED
- #define SkVertices_DEFINED
- #include "include/core/SkColor.h"
- #include "include/core/SkData.h"
- #include "include/core/SkPoint.h"
- #include "include/core/SkRect.h"
- #include "include/core/SkRefCnt.h"
- /**
- * An immutable set of vertex data that can be used with SkCanvas::drawVertices.
- */
- class SK_API SkVertices : public SkNVRefCnt<SkVertices> {
- public:
- // BoneIndices indicates which (of a maximum of 4 bones) a given vertex will interpolate
- // between. To indicate that a slot is not used, the convention is to assign the bone index
- // to 0.
- struct BoneIndices {
- uint32_t indices[4];
- uint32_t& operator[] (int i) {
- SkASSERT(i >= 0);
- SkASSERT(i < 4);
- return indices[i];
- }
- const uint32_t& operator[] (int i) const {
- SkASSERT(i >= 0);
- SkASSERT(i < 4);
- return indices[i];
- }
- };
- // BoneWeights stores the interpolation weight for each of the (maximum of 4) bones a given
- // vertex interpolates between. To indicate that a slot is not used, the weight for that
- // slot should be 0.
- struct BoneWeights {
- float weights[4];
- float& operator[] (int i) {
- SkASSERT(i >= 0);
- SkASSERT(i < 4);
- return weights[i];
- }
- const float& operator[] (int i) const {
- SkASSERT(i >= 0);
- SkASSERT(i < 4);
- return weights[i];
- }
- };
- // Bone stores a 3x2 transformation matrix in column major order:
- // | scaleX skewX transX |
- // | skewY scaleY transY |
- // SkRSXform is insufficient because bones can have non uniform scale.
- struct Bone {
- float values[6];
- float& operator[] (int i) {
- SkASSERT(i >= 0);
- SkASSERT(i < 6);
- return values[i];
- }
- const float& operator[] (int i) const {
- SkASSERT(i >= 0);
- SkASSERT(i < 6);
- return values[i];
- }
- SkPoint mapPoint(const SkPoint& point) const {
- float x = values[0] * point.x() + values[2] * point.y() + values[4];
- float y = values[1] * point.x() + values[3] * point.y() + values[5];
- return SkPoint::Make(x, y);
- }
- SkRect mapRect(const SkRect& rect) const {
- SkRect dst = SkRect::MakeEmpty();
- SkPoint quad[4];
- rect.toQuad(quad);
- for (int i = 0; i < 4; i ++) {
- quad[i] = mapPoint(quad[i]);
- }
- dst.setBoundsNoCheck(quad, 4);
- return dst;
- }
- };
- enum VertexMode {
- kTriangles_VertexMode,
- kTriangleStrip_VertexMode,
- kTriangleFan_VertexMode,
- kLast_VertexMode = kTriangleFan_VertexMode,
- };
- /**
- * Create a vertices by copying the specified arrays. texs, colors, boneIndices, and
- * boneWeights may be nullptr, and indices is ignored if indexCount == 0.
- *
- * boneIndices and boneWeights must either both be nullptr or both point to valid data.
- * If specified, they must both contain 'vertexCount' entries.
- */
- static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
- const SkPoint positions[],
- const SkPoint texs[],
- const SkColor colors[],
- const BoneIndices boneIndices[],
- const BoneWeights boneWeights[],
- int indexCount,
- const uint16_t indices[],
- bool isVolatile = true);
- static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
- const SkPoint positions[],
- const SkPoint texs[],
- const SkColor colors[],
- const BoneIndices boneIndices[],
- const BoneWeights boneWeights[],
- bool isVolatile = true) {
- return MakeCopy(mode,
- vertexCount,
- positions,
- texs,
- colors,
- boneIndices,
- boneWeights,
- 0,
- nullptr,
- isVolatile);
- }
- static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
- const SkPoint positions[],
- const SkPoint texs[],
- const SkColor colors[],
- int indexCount,
- const uint16_t indices[],
- bool isVolatile = true) {
- return MakeCopy(mode,
- vertexCount,
- positions,
- texs,
- colors,
- nullptr,
- nullptr,
- indexCount,
- indices,
- isVolatile);
- }
- static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
- const SkPoint positions[],
- const SkPoint texs[],
- const SkColor colors[],
- bool isVolatile = true) {
- return MakeCopy(mode, vertexCount, positions, texs, colors, nullptr, nullptr, isVolatile);
- }
- struct Sizes;
- enum BuilderFlags {
- kHasTexCoords_BuilderFlag = 1 << 0,
- kHasColors_BuilderFlag = 1 << 1,
- kHasBones_BuilderFlag = 1 << 2,
- kIsNonVolatile_BuilderFlag = 1 << 3,
- };
- class Builder {
- public:
- Builder(VertexMode mode, int vertexCount, int indexCount, uint32_t flags);
- bool isValid() const { return fVertices != nullptr; }
- // if the builder is invalid, these will return 0
- int vertexCount() const;
- int indexCount() const;
- bool isVolatile() const;
- SkPoint* positions();
- SkPoint* texCoords(); // returns null if there are no texCoords
- SkColor* colors(); // returns null if there are no colors
- BoneIndices* boneIndices(); // returns null if there are no bone indices
- BoneWeights* boneWeights(); // returns null if there are no bone weights
- uint16_t* indices(); // returns null if there are no indices
- // Detach the built vertices object. After the first call, this will always return null.
- sk_sp<SkVertices> detach();
- private:
- Builder(VertexMode mode, int vertexCount, int indexCount, bool isVolatile, const Sizes&);
- void init(VertexMode mode, int vertexCount, int indexCount, bool isVolatile, const Sizes&);
- // holds a partially complete object. only completed in detach()
- sk_sp<SkVertices> fVertices;
- // Extra storage for intermediate vertices in the case where the client specifies indexed
- // triangle fans. These get converted to indexed triangles when the Builder is finalized.
- std::unique_ptr<uint8_t[]> fIntermediateFanIndices;
- friend class SkVertices;
- };
- uint32_t uniqueID() const { return fUniqueID; }
- VertexMode mode() const { return fMode; }
- const SkRect& bounds() const { return fBounds; }
- bool hasColors() const { return SkToBool(this->colors()); }
- bool hasTexCoords() const { return SkToBool(this->texCoords()); }
- bool hasBones() const { return SkToBool(this->boneIndices()); }
- bool hasIndices() const { return SkToBool(this->indices()); }
- int vertexCount() const { return fVertexCnt; }
- const SkPoint* positions() const { return fPositions; }
- const SkPoint* texCoords() const { return fTexs; }
- const SkColor* colors() const { return fColors; }
- const BoneIndices* boneIndices() const { return fBoneIndices; }
- const BoneWeights* boneWeights() const { return fBoneWeights; }
- int indexCount() const { return fIndexCnt; }
- const uint16_t* indices() const { return fIndices; }
- bool isVolatile() const { return fIsVolatile; }
- sk_sp<SkVertices> applyBones(const Bone bones[], int boneCount) const;
- // returns approximate byte size of the vertices object
- size_t approximateSize() const;
- /**
- * Recreate a vertices from a buffer previously created by calling encode().
- * Returns null if the data is corrupt or the length is incorrect for the contents.
- */
- static sk_sp<SkVertices> Decode(const void* buffer, size_t length);
- /**
- * Pack the vertices object into a byte buffer. This can be used to recreate the vertices
- * by calling Decode() with the buffer.
- */
- sk_sp<SkData> encode() const;
- private:
- SkVertices() {}
- // these are needed since we've manually sized our allocation (see Builder::init)
- friend class SkNVRefCnt<SkVertices>;
- void operator delete(void* p);
- static sk_sp<SkVertices> Alloc(int vCount, int iCount, uint32_t builderFlags,
- size_t* arraySize);
- // we store this first, to pair with the refcnt in our base-class, so we don't have an
- // unnecessary pad between it and the (possibly 8-byte aligned) ptrs.
- uint32_t fUniqueID;
- // these point inside our allocation, so none of these can be "freed"
- SkPoint* fPositions;
- SkPoint* fTexs;
- SkColor* fColors;
- BoneIndices* fBoneIndices;
- BoneWeights* fBoneWeights;
- uint16_t* fIndices;
- SkRect fBounds; // computed to be the union of the fPositions[]
- int fVertexCnt;
- int fIndexCnt;
- bool fIsVolatile;
- VertexMode fMode;
- // below here is where the actual array data is stored.
- };
- #endif
|