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 
8 #ifndef SkVertices_DEFINED
9 #define SkVertices_DEFINED
10 
11 #include "SkCanvas.h"
12 #include "SkColor.h"
13 #include "SkData.h"
14 #include "SkPoint.h"
15 #include "SkRect.h"
16 #include "SkRefCnt.h"
17 
18 /**
19  * An immutable set of vertex data that can be used with SkCanvas::drawVertices.
20  */
21 class SkVertices : public SkNVRefCnt<SkVertices> {
22 public:
23     /**
24      *  Create a vertices by copying the specified arrays. texs and colors may be nullptr,
25      *  and indices is ignored if indexCount == 0.
26      */
27     static sk_sp<SkVertices> MakeCopy(SkCanvas::VertexMode mode, int vertexCount,
28                                       const SkPoint positions[],
29                                       const SkPoint texs[],
30                                       const SkColor colors[],
31                                       int indexCount,
32                                       const uint16_t indices[]);
33 
MakeCopy(SkCanvas::VertexMode mode,int vertexCount,const SkPoint positions[],const SkPoint texs[],const SkColor colors[])34     static sk_sp<SkVertices> MakeCopy(SkCanvas::VertexMode mode, int vertexCount,
35                                       const SkPoint positions[],
36                                       const SkPoint texs[],
37                                       const SkColor colors[]) {
38         return MakeCopy(mode, vertexCount, positions, texs, colors, 0, nullptr);
39     }
40 
41     struct Sizes;
42 
43     enum BuilderFlags {
44         kHasTexCoords_BuilderFlag   = 1 << 0,
45         kHasColors_BuilderFlag      = 1 << 1,
46     };
47     class Builder {
48     public:
49         Builder(SkCanvas::VertexMode mode, int vertexCount, int indexCount, uint32_t flags);
50 
isValid()51         bool isValid() const { return fVertices != nullptr; }
52 
53         // if the builder is invalid, these will return 0
54         int vertexCount() const;
55         int indexCount() const;
56         SkPoint* positions();
57         SkPoint* texCoords();   // returns null if there are no texCoords
58         SkColor* colors();      // returns null if there are no colors
59         uint16_t* indices();    // returns null if there are no indices
60 
61         // Detach the built vertices object. After the first call, this will always return null.
62         sk_sp<SkVertices> detach();
63 
64     private:
65         Builder(SkCanvas::VertexMode mode, int vertexCount, int indexCount, const Sizes&);
66 
67         void init(SkCanvas::VertexMode mode, int vertexCount, int indexCount, const Sizes&);
68 
69         // holds a partially complete object. only completed in detach()
70         sk_sp<SkVertices> fVertices;
71 
72         friend class SkVertices;
73     };
74 
uniqueID()75     uint32_t uniqueID() const { return fUniqueID; }
mode()76     SkCanvas::VertexMode mode() const { return fMode; }
bounds()77     const SkRect& bounds() const { return fBounds; }
78 
hasColors()79     bool hasColors() const { return SkToBool(this->colors()); }
hasTexCoords()80     bool hasTexCoords() const { return SkToBool(this->texCoords()); }
hasIndices()81     bool hasIndices() const { return SkToBool(this->indices()); }
82 
vertexCount()83     int vertexCount() const { return fVertexCnt; }
positions()84     const SkPoint* positions() const { return fPositions; }
texCoords()85     const SkPoint* texCoords() const { return fTexs; }
colors()86     const SkColor* colors() const { return fColors; }
87 
indexCount()88     int indexCount() const { return fIndexCnt; }
indices()89     const uint16_t* indices() const { return fIndices; }
90 
91     // returns approximate byte size of the vertices object
92     size_t approximateSize() const;
93 
94     /**
95      *  Recreate a vertices from a buffer previously created by calling encode().
96      *  Returns null if the data is corrupt or the length is incorrect for the contents.
97      */
98     static sk_sp<SkVertices> Decode(const void* buffer, size_t length);
99 
100     /**
101      *  Pack the vertices object into a byte buffer. This can be used to recreate the vertices
102      *  by calling Decode() with the buffer.
103      */
104     sk_sp<SkData> encode() const;
105 
106 private:
SkVertices()107     SkVertices() {}
108 
109     // these are needed since we've manually sized our allocation (see Builder::init)
110     friend class SkNVRefCnt<SkVertices>;
delete(void * p)111     void operator delete(void* p) { ::operator delete(p); }
112 
113     static sk_sp<SkVertices> Alloc(int vCount, int iCount, uint32_t builderFlags,
114                                    size_t* arraySize);
115 
116     // we store this first, to pair with the refcnt in our base-class, so we don't have an
117     // unnecessary pad between it and the (possibly 8-byte aligned) ptrs.
118     uint32_t fUniqueID;
119 
120     // these point inside our allocation, so none of these can be "freed"
121     SkPoint*    fPositions;
122     SkPoint*    fTexs;
123     SkColor*    fColors;
124     uint16_t*   fIndices;
125 
126     SkRect  fBounds;    // computed to be the union of the fPositions[]
127     int     fVertexCnt;
128     int     fIndexCnt;
129 
130     SkCanvas::VertexMode fMode;
131     // below here is where the actual array data is stored.
132 };
133 
134 #endif
135