1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 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/SkData.h" 9cb93a386Sopenharmony_ci#include "include/core/SkMath.h" 10cb93a386Sopenharmony_ci#include "include/private/SkPathRef.h" 11cb93a386Sopenharmony_ci#include "include/private/SkTPin.h" 12cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 13cb93a386Sopenharmony_ci#include "src/core/SkBuffer.h" 14cb93a386Sopenharmony_ci#include "src/core/SkPathPriv.h" 15cb93a386Sopenharmony_ci#include "src/core/SkRRectPriv.h" 16cb93a386Sopenharmony_ci#include "src/core/SkSafeMath.h" 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci#include <cmath> 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_cienum SerializationOffsets { 21cb93a386Sopenharmony_ci kType_SerializationShift = 28, // requires 4 bits 22cb93a386Sopenharmony_ci kDirection_SerializationShift = 26, // requires 2 bits 23cb93a386Sopenharmony_ci kFillType_SerializationShift = 8, // requires 8 bits 24cb93a386Sopenharmony_ci // low-8-bits are version 25cb93a386Sopenharmony_ci kVersion_SerializationMask = 0xFF, 26cb93a386Sopenharmony_ci}; 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_cienum SerializationVersions { 29cb93a386Sopenharmony_ci // kPathPrivFirstDirection_Version = 1, 30cb93a386Sopenharmony_ci // kPathPrivLastMoveToIndex_Version = 2, 31cb93a386Sopenharmony_ci // kPathPrivTypeEnumVersion = 3, 32cb93a386Sopenharmony_ci kJustPublicData_Version = 4, // introduced Feb/2018 33cb93a386Sopenharmony_ci kVerbsAreStoredForward_Version = 5, // introduced Sept/2019 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci kMin_Version = kJustPublicData_Version, 36cb93a386Sopenharmony_ci kCurrent_Version = kVerbsAreStoredForward_Version 37cb93a386Sopenharmony_ci}; 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_cienum SerializationType { 40cb93a386Sopenharmony_ci kGeneral = 0, 41cb93a386Sopenharmony_ci kRRect = 1 42cb93a386Sopenharmony_ci}; 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_cistatic unsigned extract_version(uint32_t packed) { 45cb93a386Sopenharmony_ci return packed & kVersion_SerializationMask; 46cb93a386Sopenharmony_ci} 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_cistatic SkPathFillType extract_filltype(uint32_t packed) { 49cb93a386Sopenharmony_ci return static_cast<SkPathFillType>((packed >> kFillType_SerializationShift) & 0x3); 50cb93a386Sopenharmony_ci} 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_cistatic SerializationType extract_serializationtype(uint32_t packed) { 53cb93a386Sopenharmony_ci return static_cast<SerializationType>((packed >> kType_SerializationShift) & 0xF); 54cb93a386Sopenharmony_ci} 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////////////////////////// 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_cisize_t SkPath::writeToMemoryAsRRect(void* storage) const { 59cb93a386Sopenharmony_ci SkRect oval; 60cb93a386Sopenharmony_ci SkRRect rrect; 61cb93a386Sopenharmony_ci bool isCCW; 62cb93a386Sopenharmony_ci unsigned start; 63cb93a386Sopenharmony_ci if (fPathRef->isOval(&oval, &isCCW, &start)) { 64cb93a386Sopenharmony_ci rrect.setOval(oval); 65cb93a386Sopenharmony_ci // Convert to rrect start indices. 66cb93a386Sopenharmony_ci start *= 2; 67cb93a386Sopenharmony_ci } else if (!fPathRef->isRRect(&rrect, &isCCW, &start)) { 68cb93a386Sopenharmony_ci return 0; 69cb93a386Sopenharmony_ci } 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci // packed header, rrect, start index. 72cb93a386Sopenharmony_ci const size_t sizeNeeded = sizeof(int32_t) + SkRRect::kSizeInMemory + sizeof(int32_t); 73cb93a386Sopenharmony_ci if (!storage) { 74cb93a386Sopenharmony_ci return sizeNeeded; 75cb93a386Sopenharmony_ci } 76cb93a386Sopenharmony_ci 77cb93a386Sopenharmony_ci int firstDir = isCCW ? (int)SkPathFirstDirection::kCCW : (int)SkPathFirstDirection::kCW; 78cb93a386Sopenharmony_ci int32_t packed = (fFillType << kFillType_SerializationShift) | 79cb93a386Sopenharmony_ci (firstDir << kDirection_SerializationShift) | 80cb93a386Sopenharmony_ci (SerializationType::kRRect << kType_SerializationShift) | 81cb93a386Sopenharmony_ci kCurrent_Version; 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ci SkWBuffer buffer(storage); 84cb93a386Sopenharmony_ci buffer.write32(packed); 85cb93a386Sopenharmony_ci SkRRectPriv::WriteToBuffer(rrect, &buffer); 86cb93a386Sopenharmony_ci buffer.write32(SkToS32(start)); 87cb93a386Sopenharmony_ci buffer.padToAlign4(); 88cb93a386Sopenharmony_ci SkASSERT(sizeNeeded == buffer.pos()); 89cb93a386Sopenharmony_ci return buffer.pos(); 90cb93a386Sopenharmony_ci} 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_cisize_t SkPath::writeToMemory(void* storage) const { 93cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci if (size_t bytes = this->writeToMemoryAsRRect(storage)) { 96cb93a386Sopenharmony_ci return bytes; 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci int32_t packed = (fFillType << kFillType_SerializationShift) | 100cb93a386Sopenharmony_ci (SerializationType::kGeneral << kType_SerializationShift) | 101cb93a386Sopenharmony_ci kCurrent_Version; 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci int32_t pts = fPathRef->countPoints(); 104cb93a386Sopenharmony_ci int32_t cnx = fPathRef->countWeights(); 105cb93a386Sopenharmony_ci int32_t vbs = fPathRef->countVerbs(); 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci SkSafeMath safe; 108cb93a386Sopenharmony_ci size_t size = 4 * sizeof(int32_t); 109cb93a386Sopenharmony_ci size = safe.add(size, safe.mul(pts, sizeof(SkPoint))); 110cb93a386Sopenharmony_ci size = safe.add(size, safe.mul(cnx, sizeof(SkScalar))); 111cb93a386Sopenharmony_ci size = safe.add(size, safe.mul(vbs, sizeof(uint8_t))); 112cb93a386Sopenharmony_ci size = safe.alignUp(size, 4); 113cb93a386Sopenharmony_ci if (!safe) { 114cb93a386Sopenharmony_ci return 0; 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci if (!storage) { 117cb93a386Sopenharmony_ci return size; 118cb93a386Sopenharmony_ci } 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci SkWBuffer buffer(storage); 121cb93a386Sopenharmony_ci buffer.write32(packed); 122cb93a386Sopenharmony_ci buffer.write32(pts); 123cb93a386Sopenharmony_ci buffer.write32(cnx); 124cb93a386Sopenharmony_ci buffer.write32(vbs); 125cb93a386Sopenharmony_ci buffer.write(fPathRef->points(), pts * sizeof(SkPoint)); 126cb93a386Sopenharmony_ci buffer.write(fPathRef->conicWeights(), cnx * sizeof(SkScalar)); 127cb93a386Sopenharmony_ci buffer.write(fPathRef->verbsBegin(), vbs * sizeof(uint8_t)); 128cb93a386Sopenharmony_ci buffer.padToAlign4(); 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci SkASSERT(buffer.pos() == size); 131cb93a386Sopenharmony_ci return size; 132cb93a386Sopenharmony_ci} 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_cisk_sp<SkData> SkPath::serialize() const { 135cb93a386Sopenharmony_ci size_t size = this->writeToMemory(nullptr); 136cb93a386Sopenharmony_ci sk_sp<SkData> data = SkData::MakeUninitialized(size); 137cb93a386Sopenharmony_ci this->writeToMemory(data->writable_data()); 138cb93a386Sopenharmony_ci return data; 139cb93a386Sopenharmony_ci} 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////// 142cb93a386Sopenharmony_ci// reading 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_cisize_t SkPath::readFromMemory(const void* storage, size_t length) { 145cb93a386Sopenharmony_ci SkRBuffer buffer(storage, length); 146cb93a386Sopenharmony_ci uint32_t packed; 147cb93a386Sopenharmony_ci if (!buffer.readU32(&packed)) { 148cb93a386Sopenharmony_ci return 0; 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci unsigned version = extract_version(packed); 151cb93a386Sopenharmony_ci if (version < kMin_Version || version > kCurrent_Version) { 152cb93a386Sopenharmony_ci return 0; 153cb93a386Sopenharmony_ci } 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_ci if (version == kJustPublicData_Version || version == kVerbsAreStoredForward_Version) { 156cb93a386Sopenharmony_ci return this->readFromMemory_EQ4Or5(storage, length); 157cb93a386Sopenharmony_ci } 158cb93a386Sopenharmony_ci return 0; 159cb93a386Sopenharmony_ci} 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_cisize_t SkPath::readAsRRect(const void* storage, size_t length) { 162cb93a386Sopenharmony_ci SkRBuffer buffer(storage, length); 163cb93a386Sopenharmony_ci uint32_t packed; 164cb93a386Sopenharmony_ci if (!buffer.readU32(&packed)) { 165cb93a386Sopenharmony_ci return 0; 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci SkASSERT(extract_serializationtype(packed) == SerializationType::kRRect); 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci uint8_t dir = (packed >> kDirection_SerializationShift) & 0x3; 171cb93a386Sopenharmony_ci SkPathFillType fillType = extract_filltype(packed); 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci SkPathDirection rrectDir; 174cb93a386Sopenharmony_ci SkRRect rrect; 175cb93a386Sopenharmony_ci int32_t start; 176cb93a386Sopenharmony_ci switch (dir) { 177cb93a386Sopenharmony_ci case (int)SkPathFirstDirection::kCW: 178cb93a386Sopenharmony_ci rrectDir = SkPathDirection::kCW; 179cb93a386Sopenharmony_ci break; 180cb93a386Sopenharmony_ci case (int)SkPathFirstDirection::kCCW: 181cb93a386Sopenharmony_ci rrectDir = SkPathDirection::kCCW; 182cb93a386Sopenharmony_ci break; 183cb93a386Sopenharmony_ci default: 184cb93a386Sopenharmony_ci return 0; 185cb93a386Sopenharmony_ci } 186cb93a386Sopenharmony_ci if (!SkRRectPriv::ReadFromBuffer(&buffer, &rrect)) { 187cb93a386Sopenharmony_ci return 0; 188cb93a386Sopenharmony_ci } 189cb93a386Sopenharmony_ci if (!buffer.readS32(&start) || start != SkTPin(start, 0, 7)) { 190cb93a386Sopenharmony_ci return 0; 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci this->reset(); 193cb93a386Sopenharmony_ci this->addRRect(rrect, rrectDir, SkToUInt(start)); 194cb93a386Sopenharmony_ci this->setFillType(fillType); 195cb93a386Sopenharmony_ci buffer.skipToAlign4(); 196cb93a386Sopenharmony_ci return buffer.pos(); 197cb93a386Sopenharmony_ci} 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_cisize_t SkPath::readFromMemory_EQ4Or5(const void* storage, size_t length) { 200cb93a386Sopenharmony_ci SkRBuffer buffer(storage, length); 201cb93a386Sopenharmony_ci uint32_t packed; 202cb93a386Sopenharmony_ci if (!buffer.readU32(&packed)) { 203cb93a386Sopenharmony_ci return 0; 204cb93a386Sopenharmony_ci } 205cb93a386Sopenharmony_ci 206cb93a386Sopenharmony_ci bool verbsAreReversed = true; 207cb93a386Sopenharmony_ci if (extract_version(packed) == kVerbsAreStoredForward_Version) { 208cb93a386Sopenharmony_ci verbsAreReversed = false; 209cb93a386Sopenharmony_ci } 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci switch (extract_serializationtype(packed)) { 212cb93a386Sopenharmony_ci case SerializationType::kRRect: 213cb93a386Sopenharmony_ci return this->readAsRRect(storage, length); 214cb93a386Sopenharmony_ci case SerializationType::kGeneral: 215cb93a386Sopenharmony_ci break; // fall out 216cb93a386Sopenharmony_ci default: 217cb93a386Sopenharmony_ci return 0; 218cb93a386Sopenharmony_ci } 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_ci int32_t pts, cnx, vbs; 221cb93a386Sopenharmony_ci if (!buffer.readS32(&pts) || !buffer.readS32(&cnx) || !buffer.readS32(&vbs)) { 222cb93a386Sopenharmony_ci return 0; 223cb93a386Sopenharmony_ci } 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_ci const SkPoint* points = buffer.skipCount<SkPoint>(pts); 226cb93a386Sopenharmony_ci const SkScalar* conics = buffer.skipCount<SkScalar>(cnx); 227cb93a386Sopenharmony_ci const uint8_t* verbs = buffer.skipCount<uint8_t>(vbs); 228cb93a386Sopenharmony_ci buffer.skipToAlign4(); 229cb93a386Sopenharmony_ci if (!buffer.isValid()) { 230cb93a386Sopenharmony_ci return 0; 231cb93a386Sopenharmony_ci } 232cb93a386Sopenharmony_ci SkASSERT(buffer.pos() <= length); 233cb93a386Sopenharmony_ci 234cb93a386Sopenharmony_ci#define CHECK_POINTS_CONICS(p, c) \ 235cb93a386Sopenharmony_ci do { \ 236cb93a386Sopenharmony_ci if (p && ((pts -= p) < 0)) { \ 237cb93a386Sopenharmony_ci return 0; \ 238cb93a386Sopenharmony_ci } \ 239cb93a386Sopenharmony_ci if (c && ((cnx -= c) < 0)) { \ 240cb93a386Sopenharmony_ci return 0; \ 241cb93a386Sopenharmony_ci } \ 242cb93a386Sopenharmony_ci } while (0) 243cb93a386Sopenharmony_ci 244cb93a386Sopenharmony_ci int verbsStep = 1; 245cb93a386Sopenharmony_ci if (verbsAreReversed) { 246cb93a386Sopenharmony_ci verbs += vbs - 1; 247cb93a386Sopenharmony_ci verbsStep = -1; 248cb93a386Sopenharmony_ci } 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci SkPath tmp; 251cb93a386Sopenharmony_ci tmp.setFillType(extract_filltype(packed)); 252cb93a386Sopenharmony_ci tmp.incReserve(pts); 253cb93a386Sopenharmony_ci for (int i = 0; i < vbs; ++i) { 254cb93a386Sopenharmony_ci switch (*verbs) { 255cb93a386Sopenharmony_ci case kMove_Verb: 256cb93a386Sopenharmony_ci CHECK_POINTS_CONICS(1, 0); 257cb93a386Sopenharmony_ci tmp.moveTo(*points++); 258cb93a386Sopenharmony_ci break; 259cb93a386Sopenharmony_ci case kLine_Verb: 260cb93a386Sopenharmony_ci CHECK_POINTS_CONICS(1, 0); 261cb93a386Sopenharmony_ci tmp.lineTo(*points++); 262cb93a386Sopenharmony_ci break; 263cb93a386Sopenharmony_ci case kQuad_Verb: 264cb93a386Sopenharmony_ci CHECK_POINTS_CONICS(2, 0); 265cb93a386Sopenharmony_ci tmp.quadTo(points[0], points[1]); 266cb93a386Sopenharmony_ci points += 2; 267cb93a386Sopenharmony_ci break; 268cb93a386Sopenharmony_ci case kConic_Verb: 269cb93a386Sopenharmony_ci CHECK_POINTS_CONICS(2, 1); 270cb93a386Sopenharmony_ci tmp.conicTo(points[0], points[1], *conics++); 271cb93a386Sopenharmony_ci points += 2; 272cb93a386Sopenharmony_ci break; 273cb93a386Sopenharmony_ci case kCubic_Verb: 274cb93a386Sopenharmony_ci CHECK_POINTS_CONICS(3, 0); 275cb93a386Sopenharmony_ci tmp.cubicTo(points[0], points[1], points[2]); 276cb93a386Sopenharmony_ci points += 3; 277cb93a386Sopenharmony_ci break; 278cb93a386Sopenharmony_ci case kClose_Verb: 279cb93a386Sopenharmony_ci tmp.close(); 280cb93a386Sopenharmony_ci break; 281cb93a386Sopenharmony_ci default: 282cb93a386Sopenharmony_ci return 0; // bad verb 283cb93a386Sopenharmony_ci } 284cb93a386Sopenharmony_ci verbs += verbsStep; 285cb93a386Sopenharmony_ci } 286cb93a386Sopenharmony_ci#undef CHECK_POINTS_CONICS 287cb93a386Sopenharmony_ci if (pts || cnx) { 288cb93a386Sopenharmony_ci return 0; // leftover points and/or conics 289cb93a386Sopenharmony_ci } 290cb93a386Sopenharmony_ci 291cb93a386Sopenharmony_ci *this = std::move(tmp); 292cb93a386Sopenharmony_ci return buffer.pos(); 293cb93a386Sopenharmony_ci} 294