1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc.
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#include "include/core/SkVertices.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkData.h"
11cb93a386Sopenharmony_ci#include "include/private/SkTo.h"
12cb93a386Sopenharmony_ci#include "src/core/SkCanvasPriv.h"
13cb93a386Sopenharmony_ci#include "src/core/SkOpts.h"
14cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h"
15cb93a386Sopenharmony_ci#include "src/core/SkSafeMath.h"
16cb93a386Sopenharmony_ci#include "src/core/SkSafeRange.h"
17cb93a386Sopenharmony_ci#include "src/core/SkVerticesPriv.h"
18cb93a386Sopenharmony_ci#include "src/core/SkWriteBuffer.h"
19cb93a386Sopenharmony_ci#include <atomic>
20cb93a386Sopenharmony_ci#include <new>
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_cistatic int32_t next_id() {
23cb93a386Sopenharmony_ci    static std::atomic<int32_t> nextID{1};
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_ci    int32_t id;
26cb93a386Sopenharmony_ci    do {
27cb93a386Sopenharmony_ci        id = nextID.fetch_add(1, std::memory_order_relaxed);
28cb93a386Sopenharmony_ci    } while (id == SK_InvalidGenID);
29cb93a386Sopenharmony_ci    return id;
30cb93a386Sopenharmony_ci}
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_cistruct SkVertices::Desc {
33cb93a386Sopenharmony_ci    VertexMode  fMode;
34cb93a386Sopenharmony_ci    int         fVertexCount,
35cb93a386Sopenharmony_ci                fIndexCount;
36cb93a386Sopenharmony_ci    bool        fHasTexs,
37cb93a386Sopenharmony_ci                fHasColors;
38cb93a386Sopenharmony_ci};
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_cistruct SkVertices::Sizes {
41cb93a386Sopenharmony_ci    Sizes(const Desc& desc) {
42cb93a386Sopenharmony_ci        SkSafeMath safe;
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci        fVSize = safe.mul(desc.fVertexCount, sizeof(SkPoint));
45cb93a386Sopenharmony_ci        fTSize = desc.fHasTexs ? safe.mul(desc.fVertexCount, sizeof(SkPoint)) : 0;
46cb93a386Sopenharmony_ci        fCSize = desc.fHasColors ? safe.mul(desc.fVertexCount, sizeof(SkColor)) : 0;
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ci        fBuilderTriFanISize = 0;
49cb93a386Sopenharmony_ci        fISize = safe.mul(desc.fIndexCount, sizeof(uint16_t));
50cb93a386Sopenharmony_ci        if (kTriangleFan_VertexMode == desc.fMode) {
51cb93a386Sopenharmony_ci            int numFanTris = 0;
52cb93a386Sopenharmony_ci            if (desc.fIndexCount) {
53cb93a386Sopenharmony_ci                fBuilderTriFanISize = fISize;
54cb93a386Sopenharmony_ci                numFanTris = desc.fIndexCount - 2;
55cb93a386Sopenharmony_ci            } else {
56cb93a386Sopenharmony_ci                numFanTris = desc.fVertexCount - 2;
57cb93a386Sopenharmony_ci                // By forcing this to become indexed we are adding a constraint to the maximum
58cb93a386Sopenharmony_ci                // number of vertices.
59cb93a386Sopenharmony_ci                if (desc.fVertexCount > (SkTo<int>(UINT16_MAX) + 1)) {
60cb93a386Sopenharmony_ci                    sk_bzero(this, sizeof(*this));
61cb93a386Sopenharmony_ci                    return;
62cb93a386Sopenharmony_ci                }
63cb93a386Sopenharmony_ci            }
64cb93a386Sopenharmony_ci            if (numFanTris <= 0) {
65cb93a386Sopenharmony_ci                sk_bzero(this, sizeof(*this));
66cb93a386Sopenharmony_ci                return;
67cb93a386Sopenharmony_ci            }
68cb93a386Sopenharmony_ci            fISize = safe.mul(numFanTris, 3 * sizeof(uint16_t));
69cb93a386Sopenharmony_ci        }
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci        fTotal = safe.add(sizeof(SkVertices),
72cb93a386Sopenharmony_ci                 safe.add(fVSize,
73cb93a386Sopenharmony_ci                 safe.add(fTSize,
74cb93a386Sopenharmony_ci                 safe.add(fCSize,
75cb93a386Sopenharmony_ci                          fISize))));
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_ci        if (safe.ok()) {
78cb93a386Sopenharmony_ci            fArrays = fVSize + fTSize + fCSize + fISize;  // just the sum of the arrays
79cb93a386Sopenharmony_ci        } else {
80cb93a386Sopenharmony_ci            sk_bzero(this, sizeof(*this));
81cb93a386Sopenharmony_ci        }
82cb93a386Sopenharmony_ci    }
83cb93a386Sopenharmony_ci
84cb93a386Sopenharmony_ci    bool isValid() const { return fTotal != 0; }
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci    size_t fTotal = 0;  // size of entire SkVertices allocation (obj + arrays)
87cb93a386Sopenharmony_ci    size_t fArrays; // size of all the data arrays (V + D + T + C + I)
88cb93a386Sopenharmony_ci    size_t fVSize;
89cb93a386Sopenharmony_ci    size_t fTSize;
90cb93a386Sopenharmony_ci    size_t fCSize;
91cb93a386Sopenharmony_ci    size_t fISize;
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci    // For indexed tri-fans this is the number of amount of space fo indices needed in the builder
94cb93a386Sopenharmony_ci    // before conversion to indexed triangles (or zero if not indexed or not a triangle fan).
95cb93a386Sopenharmony_ci    size_t fBuilderTriFanISize;
96cb93a386Sopenharmony_ci};
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ciSkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount,
99cb93a386Sopenharmony_ci                             uint32_t builderFlags) {
100cb93a386Sopenharmony_ci    bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag);
101cb93a386Sopenharmony_ci    bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag);
102cb93a386Sopenharmony_ci    this->init({mode, vertexCount, indexCount, hasTexs, hasColors});
103cb93a386Sopenharmony_ci}
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ciSkVertices::Builder::Builder(const Desc& desc) {
106cb93a386Sopenharmony_ci    this->init(desc);
107cb93a386Sopenharmony_ci}
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_civoid SkVertices::Builder::init(const Desc& desc) {
110cb93a386Sopenharmony_ci    Sizes sizes(desc);
111cb93a386Sopenharmony_ci    if (!sizes.isValid()) {
112cb93a386Sopenharmony_ci        SkASSERT(!this->isValid());
113cb93a386Sopenharmony_ci        return;
114cb93a386Sopenharmony_ci    }
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_ci    void* storage = ::operator new (sizes.fTotal);
117cb93a386Sopenharmony_ci    if (sizes.fBuilderTriFanISize) {
118cb93a386Sopenharmony_ci        fIntermediateFanIndices.reset(new uint8_t[sizes.fBuilderTriFanISize]);
119cb93a386Sopenharmony_ci    }
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci    fVertices.reset(new (storage) SkVertices);
122cb93a386Sopenharmony_ci
123cb93a386Sopenharmony_ci    // need to point past the object to store the arrays
124cb93a386Sopenharmony_ci    char* ptr = (char*)storage + sizeof(SkVertices);
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ci    // return the original ptr (or null), but then advance it by size
127cb93a386Sopenharmony_ci    auto advance = [&ptr](size_t size) {
128cb93a386Sopenharmony_ci        char* new_ptr = size ? ptr : nullptr;
129cb93a386Sopenharmony_ci        ptr += size;
130cb93a386Sopenharmony_ci        return new_ptr;
131cb93a386Sopenharmony_ci    };
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci    fVertices->fPositions      = (SkPoint*) advance(sizes.fVSize);
134cb93a386Sopenharmony_ci    fVertices->fTexs           = (SkPoint*) advance(sizes.fTSize);
135cb93a386Sopenharmony_ci    fVertices->fColors         = (SkColor*) advance(sizes.fCSize);
136cb93a386Sopenharmony_ci    fVertices->fIndices        = (uint16_t*)advance(sizes.fISize);
137cb93a386Sopenharmony_ci
138cb93a386Sopenharmony_ci    fVertices->fVertexCount    = desc.fVertexCount;
139cb93a386Sopenharmony_ci    fVertices->fIndexCount     = desc.fIndexCount;
140cb93a386Sopenharmony_ci    fVertices->fMode           = desc.fMode;
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci    // We defer assigning fBounds and fUniqueID until detach() is called
143cb93a386Sopenharmony_ci}
144cb93a386Sopenharmony_ci
145cb93a386Sopenharmony_cisk_sp<SkVertices> SkVertices::Builder::detach() {
146cb93a386Sopenharmony_ci    if (fVertices) {
147cb93a386Sopenharmony_ci        fVertices->fBounds.setBounds(fVertices->fPositions, fVertices->fVertexCount);
148cb93a386Sopenharmony_ci        if (fVertices->fMode == kTriangleFan_VertexMode) {
149cb93a386Sopenharmony_ci            if (fIntermediateFanIndices) {
150cb93a386Sopenharmony_ci                SkASSERT(fVertices->fIndexCount);
151cb93a386Sopenharmony_ci                auto tempIndices = this->indices();
152cb93a386Sopenharmony_ci                for (int t = 0; t < fVertices->fIndexCount - 2; ++t) {
153cb93a386Sopenharmony_ci                    fVertices->fIndices[3 * t + 0] = tempIndices[0];
154cb93a386Sopenharmony_ci                    fVertices->fIndices[3 * t + 1] = tempIndices[t + 1];
155cb93a386Sopenharmony_ci                    fVertices->fIndices[3 * t + 2] = tempIndices[t + 2];
156cb93a386Sopenharmony_ci                }
157cb93a386Sopenharmony_ci                fVertices->fIndexCount = 3 * (fVertices->fIndexCount - 2);
158cb93a386Sopenharmony_ci            } else {
159cb93a386Sopenharmony_ci                SkASSERT(!fVertices->fIndexCount);
160cb93a386Sopenharmony_ci                for (int t = 0; t < fVertices->fVertexCount - 2; ++t) {
161cb93a386Sopenharmony_ci                    fVertices->fIndices[3 * t + 0] = 0;
162cb93a386Sopenharmony_ci                    fVertices->fIndices[3 * t + 1] = SkToU16(t + 1);
163cb93a386Sopenharmony_ci                    fVertices->fIndices[3 * t + 2] = SkToU16(t + 2);
164cb93a386Sopenharmony_ci                }
165cb93a386Sopenharmony_ci                fVertices->fIndexCount = 3 * (fVertices->fVertexCount - 2);
166cb93a386Sopenharmony_ci            }
167cb93a386Sopenharmony_ci            fVertices->fMode = kTriangles_VertexMode;
168cb93a386Sopenharmony_ci        }
169cb93a386Sopenharmony_ci        fVertices->fUniqueID = next_id();
170cb93a386Sopenharmony_ci        return std::move(fVertices);        // this will null fVertices after the return
171cb93a386Sopenharmony_ci    }
172cb93a386Sopenharmony_ci    return nullptr;
173cb93a386Sopenharmony_ci}
174cb93a386Sopenharmony_ci
175cb93a386Sopenharmony_ciSkPoint* SkVertices::Builder::positions() {
176cb93a386Sopenharmony_ci    return fVertices ? const_cast<SkPoint*>(fVertices->fPositions) : nullptr;
177cb93a386Sopenharmony_ci}
178cb93a386Sopenharmony_ci
179cb93a386Sopenharmony_ciSkPoint* SkVertices::Builder::texCoords() {
180cb93a386Sopenharmony_ci    return fVertices ? const_cast<SkPoint*>(fVertices->fTexs) : nullptr;
181cb93a386Sopenharmony_ci}
182cb93a386Sopenharmony_ci
183cb93a386Sopenharmony_ciSkColor* SkVertices::Builder::colors() {
184cb93a386Sopenharmony_ci    return fVertices ? const_cast<SkColor*>(fVertices->fColors) : nullptr;
185cb93a386Sopenharmony_ci}
186cb93a386Sopenharmony_ci
187cb93a386Sopenharmony_ciuint16_t* SkVertices::Builder::indices() {
188cb93a386Sopenharmony_ci    if (!fVertices) {
189cb93a386Sopenharmony_ci        return nullptr;
190cb93a386Sopenharmony_ci    }
191cb93a386Sopenharmony_ci    if (fIntermediateFanIndices) {
192cb93a386Sopenharmony_ci        return reinterpret_cast<uint16_t*>(fIntermediateFanIndices.get());
193cb93a386Sopenharmony_ci    }
194cb93a386Sopenharmony_ci    return const_cast<uint16_t*>(fVertices->fIndices);
195cb93a386Sopenharmony_ci}
196cb93a386Sopenharmony_ci
197cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_cisk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
200cb93a386Sopenharmony_ci                                       const SkPoint pos[], const SkPoint texs[],
201cb93a386Sopenharmony_ci                                       const SkColor colors[],
202cb93a386Sopenharmony_ci                                       int indexCount, const uint16_t indices[]) {
203cb93a386Sopenharmony_ci    auto desc = Desc{mode, vertexCount, indexCount, !!texs, !!colors};
204cb93a386Sopenharmony_ci    Builder builder(desc);
205cb93a386Sopenharmony_ci    if (!builder.isValid()) {
206cb93a386Sopenharmony_ci        return nullptr;
207cb93a386Sopenharmony_ci    }
208cb93a386Sopenharmony_ci
209cb93a386Sopenharmony_ci    Sizes sizes(desc);
210cb93a386Sopenharmony_ci    SkASSERT(sizes.isValid());
211cb93a386Sopenharmony_ci    sk_careful_memcpy(builder.positions(), pos, sizes.fVSize);
212cb93a386Sopenharmony_ci    sk_careful_memcpy(builder.texCoords(), texs, sizes.fTSize);
213cb93a386Sopenharmony_ci    sk_careful_memcpy(builder.colors(), colors, sizes.fCSize);
214cb93a386Sopenharmony_ci    size_t isize = (mode == kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize : sizes.fISize;
215cb93a386Sopenharmony_ci    sk_careful_memcpy(builder.indices(), indices, isize);
216cb93a386Sopenharmony_ci
217cb93a386Sopenharmony_ci    return builder.detach();
218cb93a386Sopenharmony_ci}
219cb93a386Sopenharmony_ci
220cb93a386Sopenharmony_cisize_t SkVertices::approximateSize() const {
221cb93a386Sopenharmony_ci    return this->getSizes().fTotal;
222cb93a386Sopenharmony_ci}
223cb93a386Sopenharmony_ci
224cb93a386Sopenharmony_ciSkVertices::Sizes SkVertices::getSizes() const {
225cb93a386Sopenharmony_ci    Sizes sizes({fMode, fVertexCount, fIndexCount, !!fTexs, !!fColors});
226cb93a386Sopenharmony_ci    SkASSERT(sizes.isValid());
227cb93a386Sopenharmony_ci    return sizes;
228cb93a386Sopenharmony_ci}
229cb93a386Sopenharmony_civoid SkVertices::dump(std::string& desc, int depth) const {
230cb93a386Sopenharmony_ci    std::string split(depth, '\t');
231cb93a386Sopenharmony_ci    desc += split + "\n SkVertices:{ \n";
232cb93a386Sopenharmony_ci    desc += split + "\t fUniqueID: " + std::to_string(fUniqueID) + "\n";
233cb93a386Sopenharmony_ci    if (fPositions != nullptr) {
234cb93a386Sopenharmony_ci        fPositions->dump(desc, depth + 1);
235cb93a386Sopenharmony_ci    } else {
236cb93a386Sopenharmony_ci        desc += split + "\t fPositions: nullptr\n";
237cb93a386Sopenharmony_ci    }
238cb93a386Sopenharmony_ci
239cb93a386Sopenharmony_ci    if (fTexs != nullptr) {
240cb93a386Sopenharmony_ci        fTexs->dump(desc, depth + 1);
241cb93a386Sopenharmony_ci    } else {
242cb93a386Sopenharmony_ci        desc += split + "\t fTexs: nullptr\n";
243cb93a386Sopenharmony_ci    }
244cb93a386Sopenharmony_ci
245cb93a386Sopenharmony_ci    if (fColors != nullptr) {
246cb93a386Sopenharmony_ci        desc += split + "\t fColors: " + std::to_string(*fColors) + "\n";
247cb93a386Sopenharmony_ci    } else {
248cb93a386Sopenharmony_ci        desc += split + "\t fColors: nullptr\n";
249cb93a386Sopenharmony_ci    }
250cb93a386Sopenharmony_ci
251cb93a386Sopenharmony_ci    if (fIndices != nullptr) {
252cb93a386Sopenharmony_ci        desc += split + "\t fIndices: " + std::to_string(*fIndices) + "\n";
253cb93a386Sopenharmony_ci    } else {
254cb93a386Sopenharmony_ci        desc += split + "\t fIndices: nullptr\n";
255cb93a386Sopenharmony_ci    }
256cb93a386Sopenharmony_ci
257cb93a386Sopenharmony_ci    fBounds.dump(desc, depth + 1);
258cb93a386Sopenharmony_ci    desc += split + "\t fVertexCount: " + std::to_string(fVertexCount) + "\n";
259cb93a386Sopenharmony_ci    desc += split + "\t fIndexCount: " + std::to_string(fIndexCount) + "\n";
260cb93a386Sopenharmony_ci    desc += split + "\t fMode: " + std::to_string(static_cast<int>(fMode)) + "\n";
261cb93a386Sopenharmony_ci    desc += split + "}\n";
262cb93a386Sopenharmony_ci}
263cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
264cb93a386Sopenharmony_ci
265cb93a386Sopenharmony_ci// storage = packed | vertex_count | index_count | attr_count
266cb93a386Sopenharmony_ci//           | pos[] | custom[] | texs[] | colors[] | indices[]
267cb93a386Sopenharmony_ci
268cb93a386Sopenharmony_ci#define kMode_Mask          0x0FF
269cb93a386Sopenharmony_ci#define kHasTexs_Mask       0x100
270cb93a386Sopenharmony_ci#define kHasColors_Mask     0x200
271cb93a386Sopenharmony_ci
272cb93a386Sopenharmony_civoid SkVerticesPriv::encode(SkWriteBuffer& buffer) const {
273cb93a386Sopenharmony_ci    // packed has room for additional flags in the future
274cb93a386Sopenharmony_ci    uint32_t packed = static_cast<uint32_t>(fVertices->fMode);
275cb93a386Sopenharmony_ci    SkASSERT((packed & ~kMode_Mask) == 0);  // our mode fits in the mask bits
276cb93a386Sopenharmony_ci    if (fVertices->fTexs) {
277cb93a386Sopenharmony_ci        packed |= kHasTexs_Mask;
278cb93a386Sopenharmony_ci    }
279cb93a386Sopenharmony_ci    if (fVertices->fColors) {
280cb93a386Sopenharmony_ci        packed |= kHasColors_Mask;
281cb93a386Sopenharmony_ci    }
282cb93a386Sopenharmony_ci
283cb93a386Sopenharmony_ci    SkVertices::Sizes sizes = fVertices->getSizes();
284cb93a386Sopenharmony_ci    SkASSERT(!sizes.fBuilderTriFanISize);
285cb93a386Sopenharmony_ci
286cb93a386Sopenharmony_ci    // Header
287cb93a386Sopenharmony_ci    buffer.writeUInt(packed);
288cb93a386Sopenharmony_ci    buffer.writeInt(fVertices->fVertexCount);
289cb93a386Sopenharmony_ci    buffer.writeInt(fVertices->fIndexCount);
290cb93a386Sopenharmony_ci
291cb93a386Sopenharmony_ci    // Data arrays
292cb93a386Sopenharmony_ci    buffer.writeByteArray(fVertices->fPositions, sizes.fVSize);
293cb93a386Sopenharmony_ci    buffer.writeByteArray(fVertices->fTexs, sizes.fTSize);
294cb93a386Sopenharmony_ci    buffer.writeByteArray(fVertices->fColors, sizes.fCSize);
295cb93a386Sopenharmony_ci    // if index-count is odd, we won't be 4-bytes aligned, so we call the pad version
296cb93a386Sopenharmony_ci    buffer.writeByteArray(fVertices->fIndices, sizes.fISize);
297cb93a386Sopenharmony_ci}
298cb93a386Sopenharmony_ci
299cb93a386Sopenharmony_cisk_sp<SkVertices> SkVerticesPriv::Decode(SkReadBuffer& buffer) {
300cb93a386Sopenharmony_ci    auto decode = [](SkReadBuffer& buffer) -> sk_sp<SkVertices> {
301cb93a386Sopenharmony_ci        SkSafeRange safe;
302cb93a386Sopenharmony_ci        bool hasCustomData = buffer.isVersionLT(SkPicturePriv::kVerticesRemoveCustomData_Version);
303cb93a386Sopenharmony_ci
304cb93a386Sopenharmony_ci        const uint32_t packed = buffer.readUInt();
305cb93a386Sopenharmony_ci        const int vertexCount = safe.checkGE(buffer.readInt(), 0);
306cb93a386Sopenharmony_ci        const int indexCount = safe.checkGE(buffer.readInt(), 0);
307cb93a386Sopenharmony_ci        const int attrCount = hasCustomData ? safe.checkGE(buffer.readInt(), 0) : 0;
308cb93a386Sopenharmony_ci        const SkVertices::VertexMode mode = safe.checkLE<SkVertices::VertexMode>(
309cb93a386Sopenharmony_ci                packed & kMode_Mask, SkVertices::kLast_VertexMode);
310cb93a386Sopenharmony_ci        const bool hasTexs = SkToBool(packed & kHasTexs_Mask);
311cb93a386Sopenharmony_ci        const bool hasColors = SkToBool(packed & kHasColors_Mask);
312cb93a386Sopenharmony_ci
313cb93a386Sopenharmony_ci        // Check that the header fields and buffer are valid. If this is data with the experimental
314cb93a386Sopenharmony_ci        // custom attributes feature - we don't support that any more.
315cb93a386Sopenharmony_ci        if (!safe || !buffer.isValid() || attrCount) {
316cb93a386Sopenharmony_ci            return nullptr;
317cb93a386Sopenharmony_ci        }
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ci        const SkVertices::Desc desc{mode, vertexCount, indexCount, hasTexs, hasColors};
320cb93a386Sopenharmony_ci        SkVertices::Sizes sizes(desc);
321cb93a386Sopenharmony_ci        if (!sizes.isValid()) {
322cb93a386Sopenharmony_ci            return nullptr;
323cb93a386Sopenharmony_ci        }
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_ci        SkVertices::Builder builder(desc);
326cb93a386Sopenharmony_ci        if (!builder.isValid()) {
327cb93a386Sopenharmony_ci            return nullptr;
328cb93a386Sopenharmony_ci        }
329cb93a386Sopenharmony_ci
330cb93a386Sopenharmony_ci        buffer.readByteArray(builder.positions(), sizes.fVSize);
331cb93a386Sopenharmony_ci        if (hasCustomData) {
332cb93a386Sopenharmony_ci            size_t customDataSize = 0;
333cb93a386Sopenharmony_ci            buffer.skipByteArray(&customDataSize);
334cb93a386Sopenharmony_ci            if (customDataSize != 0) {
335cb93a386Sopenharmony_ci                return nullptr;
336cb93a386Sopenharmony_ci            }
337cb93a386Sopenharmony_ci        }
338cb93a386Sopenharmony_ci        buffer.readByteArray(builder.texCoords(), sizes.fTSize);
339cb93a386Sopenharmony_ci        buffer.readByteArray(builder.colors(), sizes.fCSize);
340cb93a386Sopenharmony_ci        size_t isize = (mode == SkVertices::kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize
341cb93a386Sopenharmony_ci                                                                     : sizes.fISize;
342cb93a386Sopenharmony_ci        buffer.readByteArray(builder.indices(), isize);
343cb93a386Sopenharmony_ci
344cb93a386Sopenharmony_ci        if (!buffer.isValid()) {
345cb93a386Sopenharmony_ci            return nullptr;
346cb93a386Sopenharmony_ci        }
347cb93a386Sopenharmony_ci
348cb93a386Sopenharmony_ci        if (indexCount > 0) {
349cb93a386Sopenharmony_ci            // validate that the indices are in range
350cb93a386Sopenharmony_ci            const uint16_t* indices = builder.indices();
351cb93a386Sopenharmony_ci            for (int i = 0; i < indexCount; ++i) {
352cb93a386Sopenharmony_ci                if (indices[i] >= (unsigned)vertexCount) {
353cb93a386Sopenharmony_ci                    return nullptr;
354cb93a386Sopenharmony_ci                }
355cb93a386Sopenharmony_ci            }
356cb93a386Sopenharmony_ci        }
357cb93a386Sopenharmony_ci
358cb93a386Sopenharmony_ci        return builder.detach();
359cb93a386Sopenharmony_ci    };
360cb93a386Sopenharmony_ci
361cb93a386Sopenharmony_ci    if (auto verts = decode(buffer)) {
362cb93a386Sopenharmony_ci        return verts;
363cb93a386Sopenharmony_ci    }
364cb93a386Sopenharmony_ci    buffer.validate(false);
365cb93a386Sopenharmony_ci    return nullptr;
366cb93a386Sopenharmony_ci}
367cb93a386Sopenharmony_ci
368cb93a386Sopenharmony_civoid SkVertices::operator delete(void* p) {
369cb93a386Sopenharmony_ci    ::operator delete(p);
370cb93a386Sopenharmony_ci}
371