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