Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkPath_serial.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2018 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
12#include "include/core/SkRect.h"
22#include "src/base/SkBuffer.h"
23#include "src/base/SkSafeMath.h"
25#include "src/core/SkPathPriv.h"
27
28#include <cstddef>
29#include <cstdint>
30
32 kType_SerializationShift = 28, // requires 4 bits
33 kDirection_SerializationShift = 26, // requires 2 bits
34 kFillType_SerializationShift = 8, // requires 8 bits
35 // low-8-bits are version
37};
38
40 // kPathPrivFirstDirection_Version = 1,
41 // kPathPrivLastMoveToIndex_Version = 2,
42 // kPathPrivTypeEnumVersion = 3,
43 kJustPublicData_Version = 4, // introduced Feb/2018
44 kVerbsAreStoredForward_Version = 5, // introduced Sept/2019
45
48};
49
54
55static unsigned extract_version(uint32_t packed) {
56 return packed & kVersion_SerializationMask;
57}
58
59static SkPathFillType extract_filltype(uint32_t packed) {
60 return static_cast<SkPathFillType>((packed >> kFillType_SerializationShift) & 0x3);
61}
62
64 return static_cast<SerializationType>((packed >> kType_SerializationShift) & 0xF);
65}
66
67///////////////////////////////////////////////////////////////////////////////////////////////////
68
69size_t SkPath::writeToMemoryAsRRect(void* storage) const {
72 bool isCCW;
73 unsigned start;
74 if (fPathRef->isOval(&oval, &isCCW, &start)) {
75 rrect.setOval(oval);
76 // Convert to rrect start indices.
77 start *= 2;
78 } else if (!fPathRef->isRRect(&rrect, &isCCW, &start)) {
79 return 0;
80 }
81
82 // packed header, rrect, start index.
83 const size_t sizeNeeded = sizeof(int32_t) + SkRRect::kSizeInMemory + sizeof(int32_t);
84 if (!storage) {
85 return sizeNeeded;
86 }
87
88 int firstDir = isCCW ? (int)SkPathFirstDirection::kCCW : (int)SkPathFirstDirection::kCW;
89 int32_t packed = (fFillType << kFillType_SerializationShift) |
90 (firstDir << kDirection_SerializationShift) |
93
94 SkWBuffer buffer(storage);
95 buffer.write32(packed);
97 buffer.write32(SkToS32(start));
98 buffer.padToAlign4();
99 SkASSERT(sizeNeeded == buffer.pos());
100 return buffer.pos();
101}
102
103size_t SkPath::writeToMemory(void* storage) const {
104 SkDEBUGCODE(this->validate();)
105
106 if (size_t bytes = this->writeToMemoryAsRRect(storage)) {
107 return bytes;
108 }
109
110 int32_t packed = (fFillType << kFillType_SerializationShift) |
113
114 int32_t pts = fPathRef->countPoints();
115 int32_t cnx = fPathRef->countWeights();
116 int32_t vbs = fPathRef->countVerbs();
117
118 SkSafeMath safe;
119 size_t size = 4 * sizeof(int32_t);
120 size = safe.add(size, safe.mul(pts, sizeof(SkPoint)));
121 size = safe.add(size, safe.mul(cnx, sizeof(SkScalar)));
122 size = safe.add(size, safe.mul(vbs, sizeof(uint8_t)));
123 size = safe.alignUp(size, 4);
124 if (!safe) {
125 return 0;
126 }
127 if (!storage) {
128 return size;
129 }
130
131 SkWBuffer buffer(storage);
132 buffer.write32(packed);
133 buffer.write32(pts);
134 buffer.write32(cnx);
135 buffer.write32(vbs);
136 buffer.write(fPathRef->points(), pts * sizeof(SkPoint));
137 buffer.write(fPathRef->conicWeights(), cnx * sizeof(SkScalar));
138 buffer.write(fPathRef->verbsBegin(), vbs * sizeof(uint8_t));
139 buffer.padToAlign4();
140
141 SkASSERT(buffer.pos() == size);
142 return size;
143}
144
146 size_t size = this->writeToMemory(nullptr);
148 this->writeToMemory(data->writable_data());
149 return data;
150}
151
152//////////////////////////////////////////////////////////////////////////////////////////////////
153// reading
154
155size_t SkPath::readFromMemory(const void* storage, size_t length) {
156 SkRBuffer buffer(storage, length);
157 uint32_t packed;
158 if (!buffer.readU32(&packed)) {
159 return 0;
160 }
161 unsigned version = extract_version(packed);
162 if (version < kMin_Version || version > kCurrent_Version) {
163 return 0;
164 }
165
166 if (version == kJustPublicData_Version || version == kVerbsAreStoredForward_Version) {
167 return this->readFromMemory_EQ4Or5(storage, length);
168 }
169 return 0;
170}
171
172size_t SkPath::readAsRRect(const void* storage, size_t length) {
173 SkRBuffer buffer(storage, length);
174 uint32_t packed;
175 if (!buffer.readU32(&packed)) {
176 return 0;
177 }
178
180
181 uint8_t dir = (packed >> kDirection_SerializationShift) & 0x3;
182 SkPathFillType fillType = extract_filltype(packed);
183
184 SkPathDirection rrectDir;
186 int32_t start;
187 switch (dir) {
189 rrectDir = SkPathDirection::kCW;
190 break;
192 rrectDir = SkPathDirection::kCCW;
193 break;
194 default:
195 return 0;
196 }
197 if (!SkRRectPriv::ReadFromBuffer(&buffer, &rrect)) {
198 return 0;
199 }
200 if (!buffer.readS32(&start) || start != SkTPin(start, 0, 7)) {
201 return 0;
202 }
203 this->reset();
204 this->addRRect(rrect, rrectDir, SkToUInt(start));
205 this->setFillType(fillType);
206 buffer.skipToAlign4();
207 return buffer.pos();
208}
209
210size_t SkPath::readFromMemory_EQ4Or5(const void* storage, size_t length) {
211 SkRBuffer buffer(storage, length);
212 uint32_t packed;
213 if (!buffer.readU32(&packed)) {
214 return 0;
215 }
216
217 bool verbsAreReversed = true;
219 verbsAreReversed = false;
220 }
221
222 switch (extract_serializationtype(packed)) {
224 return this->readAsRRect(storage, length);
226 break; // fall out
227 default:
228 return 0;
229 }
230
231 int32_t pts, cnx, vbs;
232 if (!buffer.readS32(&pts) || !buffer.readS32(&cnx) || !buffer.readS32(&vbs)) {
233 return 0;
234 }
235
236 const SkPoint* points = buffer.skipCount<SkPoint>(pts);
237 const SkScalar* conics = buffer.skipCount<SkScalar>(cnx);
238 const uint8_t* verbs = buffer.skipCount<uint8_t>(vbs);
239 buffer.skipToAlign4();
240 if (!buffer.isValid()) {
241 return 0;
242 }
243 SkASSERT(buffer.pos() <= length);
244
245 if (vbs == 0) {
246 if (pts == 0 && cnx == 0) {
247 reset();
249 return buffer.pos();
250 }
251 // No verbs but points and/or conic weights is a not a valid path.
252 return 0;
253 }
254
255 SkAutoMalloc reversedStorage;
256 if (verbsAreReversed) {
257 uint8_t* tmpVerbs = (uint8_t*)reversedStorage.reset(vbs);
258 for (int i = 0; i < vbs; ++i) {
259 tmpVerbs[i] = verbs[vbs - i - 1];
260 }
261 verbs = tmpVerbs;
262 }
263
264 SkPathVerbAnalysis analysis = sk_path_analyze_verbs(verbs, vbs);
265 if (!analysis.valid || analysis.points != pts || analysis.weights != cnx) {
266 return 0;
267 }
268 *this = SkPathPriv::MakePath(analysis, points, verbs, vbs, conics,
269 extract_filltype(packed), false);
270 return buffer.pos();
271}
static const int points[]
#define SkASSERT(cond)
Definition SkAssert.h:116
@ kCurrent_Version
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
SkPathFirstDirection
Definition SkPathEnums.h:19
SkPathVerbAnalysis sk_path_analyze_verbs(const uint8_t verbs[], int count)
Definition SkPath.cpp:3447
SkPathDirection
Definition SkPathTypes.h:34
SkPathFillType
Definition SkPathTypes.h:11
static unsigned extract_version(uint32_t packed)
SerializationType
@ kGeneral
@ kRRect
static SkPathFillType extract_filltype(uint32_t packed)
SerializationVersions
@ kJustPublicData_Version
@ kMin_Version
@ kCurrent_Version
@ kVerbsAreStoredForward_Version
SerializationOffsets
@ kType_SerializationShift
@ kFillType_SerializationShift
@ kDirection_SerializationShift
@ kVersion_SerializationMask
static SerializationType extract_serializationtype(uint32_t packed)
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition SkTPin.h:19
constexpr int32_t SkToS32(S x)
Definition SkTo.h:25
constexpr unsigned SkToUInt(S x)
Definition SkTo.h:30
Type::kYUV Type::kRGBA() int(0.7 *637)
void * reset(size_t size=0, OnShrink shrink=kAlloc_OnShrink)
static sk_sp< SkData > MakeUninitialized(size_t length)
Definition SkData.cpp:116
static SkPath MakePath(const SkPathVerbAnalysis &analysis, const SkPoint points[], const uint8_t verbs[], int verbCount, const SkScalar conics[], SkPathFillType fillType, bool isVolatile)
Definition SkPathPriv.h:425
int countWeights() const
Definition SkPathRef.h:311
const SkPoint * points() const
Definition SkPathRef.h:328
const SkScalar * conicWeights() const
Definition SkPathRef.h:335
bool isRRect(SkRRect *rrect, bool *isCCW, unsigned *start) const
int countPoints() const
Definition SkPathRef.h:309
const uint8_t * verbsBegin() const
Definition SkPathRef.h:318
int countVerbs() const
Definition SkPathRef.h:310
bool isOval(SkRect *rect, bool *isCCW, unsigned *start) const
Definition SkPathRef.h:243
size_t readFromMemory(const void *buffer, size_t length)
void setFillType(SkPathFillType ft)
Definition SkPath.h:235
SkPath & addRRect(const SkRRect &rrect, SkPathDirection dir=SkPathDirection::kCW)
Definition SkPath.cpp:990
SkPath & reset()
Definition SkPath.cpp:360
sk_sp< SkData > serialize() const
size_t writeToMemory(void *buffer) const
static bool ReadFromBuffer(SkRBuffer *buffer, SkRRect *rr)
Definition SkRRect.cpp:623
static void WriteToBuffer(const SkRRect &rr, SkWBuffer *buffer)
Definition SkRRect.cpp:605
void setOval(const SkRect &oval)
Definition SkRRect.cpp:30
static constexpr size_t kSizeInMemory
Definition SkRRect.h:422
size_t add(size_t x, size_t y)
Definition SkSafeMath.h:33
size_t alignUp(size_t x, size_t alignment)
Definition SkSafeMath.h:54
size_t mul(size_t x, size_t y)
Definition SkSafeMath.h:29
float SkScalar
Definition extension.cpp:12
static const uint8_t buffer[]
size_t length
SkRRect rrect
Definition SkRecords.h:232
SkRect oval
Definition SkRecords.h:249
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition switches.h:145