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