@octane-xplat/smooth-corners 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -11
- package/src/layout-child.ts +2 -10
- package/src/layout-child.web.ts +1 -7
- package/dist/native/index.js +0 -2
- package/dist/native/node_modules/.pnpm/@lisse_core@0.7.2/node_modules/@lisse/core/dist/chunk-BL6ZAFLB.js +0 -477
- package/dist/native/octane-client-build.json +0 -8
- package/dist/native/packages/smooth-corners/src/SmoothCorners.tsrx.js +0 -77
- package/dist/native/packages/smooth-corners/src/apply.android.js +0 -95
- package/dist/native/packages/smooth-corners/src/apply.ios.js +0 -92
- package/dist/native/packages/smooth-corners/src/layout-child.js +0 -61
- package/dist/native/packages/smooth-corners/src/path.js +0 -424
- package/dist/web/index.js +0 -2
- package/dist/web/node_modules/.pnpm/@lisse_core@0.7.2/node_modules/@lisse/core/dist/chunk-BL6ZAFLB.js +0 -477
- package/dist/web/octane-client-build.json +0 -8
- package/dist/web/packages/smooth-corners/src/SmoothCorners.web.tsrx.js +0 -69
- package/dist/web/packages/smooth-corners/src/layout-child.web.js +0 -94
- package/dist/web/packages/smooth-corners/src/path.js +0 -453
|
@@ -1,453 +0,0 @@
|
|
|
1
|
-
import { a as st, i as ft, p as ot } from "../../../node_modules/.pnpm/@lisse_core@0.7.2/node_modules/@lisse/core/dist/chunk-BL6ZAFLB.js";
|
|
2
|
-
//#region src/path.ts
|
|
3
|
-
/** Shared smooth-corner path generation — pure TS, no DOM. Emits one
|
|
4
|
-
* `PathCommand[]` (absolute coords, arcs already center-parameterized) that
|
|
5
|
-
* web stringifies to `d`, iOS feeds `CGPathAdd*`, Android feeds
|
|
6
|
-
* `android.graphics.Path`, and macOS feeds `NSBezierPath`.
|
|
7
|
-
*
|
|
8
|
-
* Lisse curves (`squircle`/`superellipse`/`clothoid`/`arc`) delegate to
|
|
9
|
-
* `@lisse/core/path`; `continuous` is our own builder — the Rosenfeld
|
|
10
|
-
* `UIBezierPath` constants reproducing Apple's fixed continuous corner
|
|
11
|
-
* (~0.25 px from SwiftUI `.continuous`; Lisse issue #103 /
|
|
12
|
-
* tools/apple-continuous-export). */
|
|
13
|
-
function resolveOne(c) {
|
|
14
|
-
const cfg = typeof c === "number" ? { radius: c } : c ?? { radius: 0 };
|
|
15
|
-
return {
|
|
16
|
-
radius: cfg.radius,
|
|
17
|
-
curve: cfg.curve ?? "continuous",
|
|
18
|
-
smoothing: cfg.smoothing ?? .65,
|
|
19
|
-
exponent: cfg.exponent ?? 4,
|
|
20
|
-
preserveSmoothing: cfg.preserveSmoothing ?? true
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
function resolveOptions(options) {
|
|
24
|
-
if (typeof options === "number") {
|
|
25
|
-
const c = resolveOne(options);
|
|
26
|
-
return {
|
|
27
|
-
topLeft: c,
|
|
28
|
-
topRight: c,
|
|
29
|
-
bottomRight: c,
|
|
30
|
-
bottomLeft: c
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
if ("radius" in options) {
|
|
34
|
-
const c = resolveOne(options);
|
|
35
|
-
return {
|
|
36
|
-
topLeft: c,
|
|
37
|
-
topRight: c,
|
|
38
|
-
bottomRight: c,
|
|
39
|
-
bottomLeft: c
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
const p = options;
|
|
43
|
-
return {
|
|
44
|
-
topLeft: resolveOne(p.topLeft),
|
|
45
|
-
topRight: resolveOne(p.topRight),
|
|
46
|
-
bottomRight: resolveOne(p.bottomRight),
|
|
47
|
-
bottomLeft: resolveOne(p.bottomLeft)
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
/** Shoulder extent along each adjacent edge, as a multiple of R. */
|
|
51
|
-
var CONT_P = 1.528665;
|
|
52
|
-
var CONT_CURVE = [
|
|
53
|
-
[1.08849296, 0],
|
|
54
|
-
[.86840694, 0],
|
|
55
|
-
[.63149379, .07491139],
|
|
56
|
-
[.37282383, .16905956],
|
|
57
|
-
[.16905956, .37282383],
|
|
58
|
-
[.07491139, .63149379],
|
|
59
|
-
[0, .86840694],
|
|
60
|
-
[0, 1.08849296],
|
|
61
|
-
[0, 1.52866498]
|
|
62
|
-
];
|
|
63
|
-
var CONT_CURVE_YX = CONT_CURVE.map(([x, y]) => [y, x]);
|
|
64
|
-
/** Absolute `C` commands for one continuous corner. `p` returned separately —
|
|
65
|
-
* the tangent distance from the vertex along the incoming edge. */
|
|
66
|
-
function continuousCorner(w, h, radius, budget, orient) {
|
|
67
|
-
const r = Math.min(radius, budget / CONT_P);
|
|
68
|
-
const p = CONT_P * r;
|
|
69
|
-
if (r <= 0) return {
|
|
70
|
-
p: 0,
|
|
71
|
-
cmds: []
|
|
72
|
-
};
|
|
73
|
-
let fx;
|
|
74
|
-
let fy;
|
|
75
|
-
let seq = CONT_CURVE;
|
|
76
|
-
switch (orient) {
|
|
77
|
-
case "TR":
|
|
78
|
-
fx = (x, _y) => w - x * r;
|
|
79
|
-
fy = (_x, y) => y * r;
|
|
80
|
-
break;
|
|
81
|
-
case "BR":
|
|
82
|
-
fx = (x, _y) => w - x * r;
|
|
83
|
-
fy = (_x, y) => h - y * r;
|
|
84
|
-
seq = CONT_CURVE_YX;
|
|
85
|
-
break;
|
|
86
|
-
case "BL":
|
|
87
|
-
fx = (x, _y) => x * r;
|
|
88
|
-
fy = (_x, y) => h - y * r;
|
|
89
|
-
break;
|
|
90
|
-
case "TL":
|
|
91
|
-
fx = (x, _y) => x * r;
|
|
92
|
-
fy = (_x, y) => 0 + y * r;
|
|
93
|
-
seq = CONT_CURVE_YX;
|
|
94
|
-
}
|
|
95
|
-
const cmds = [];
|
|
96
|
-
for (let i = 0; i < seq.length; i += 3) {
|
|
97
|
-
const [c1, c2, e] = [
|
|
98
|
-
seq[i],
|
|
99
|
-
seq[i + 1],
|
|
100
|
-
seq[i + 2]
|
|
101
|
-
];
|
|
102
|
-
cmds.push({
|
|
103
|
-
c: "C",
|
|
104
|
-
x1: fx(c1[0], c1[1]),
|
|
105
|
-
y1: fy(c1[0], c1[1]),
|
|
106
|
-
x2: fx(c2[0], c2[1]),
|
|
107
|
-
y2: fy(c2[0], c2[1]),
|
|
108
|
-
x: fx(e[0], e[1]),
|
|
109
|
-
y: fy(e[0], e[1])
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
return {
|
|
113
|
-
p,
|
|
114
|
-
cmds
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
/** Parse a curve builder's per-orient relative segment starting at `pen`.
|
|
118
|
-
* Returns absolute commands. Lisse segments only emit `c`/`a`/`l`. */
|
|
119
|
-
function segmentCommands(seg, pen) {
|
|
120
|
-
return parsePath(seg, pen.x, pen.y).filter((c) => c.c !== "M");
|
|
121
|
-
}
|
|
122
|
-
var TOKEN = /[a-zA-Z]|[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
|
|
123
|
-
var ARITY = {
|
|
124
|
-
M: 2,
|
|
125
|
-
L: 2,
|
|
126
|
-
H: 1,
|
|
127
|
-
V: 1,
|
|
128
|
-
C: 6,
|
|
129
|
-
S: 4,
|
|
130
|
-
Q: 4,
|
|
131
|
-
T: 2,
|
|
132
|
-
A: 7,
|
|
133
|
-
Z: 0
|
|
134
|
-
};
|
|
135
|
-
/** Endpoint→center for a circular SVG arc (φ=0 — every Lisse emitter).
|
|
136
|
-
* Non-circular or rotated arcs throw: unsupported is loud, not silent. */
|
|
137
|
-
function arcToCenter(x0, y0, rx, ry, rot, largeArc, sweep, x1, y1) {
|
|
138
|
-
if (x0 === x1 && y0 === y1) return null;
|
|
139
|
-
if (rx <= 0 || ry <= 0) return null;
|
|
140
|
-
if (rx !== ry || rot !== 0) throw new Error(`smooth-corners: only circular unrotated arcs are supported (got a ${rx} ${ry} ${rot})`);
|
|
141
|
-
const dx = (x0 - x1) / 2;
|
|
142
|
-
const dy = (y0 - y1) / 2;
|
|
143
|
-
const d2 = dx * dx + dy * dy;
|
|
144
|
-
let r = rx;
|
|
145
|
-
const lambda = d2 / (r * r);
|
|
146
|
-
if (lambda > 1) r *= Math.sqrt(lambda);
|
|
147
|
-
const h = Math.sqrt(Math.max(0, (r * r - d2) / d2));
|
|
148
|
-
const sign = largeArc !== sweep ? 1 : -1;
|
|
149
|
-
const cx = (x0 + x1) / 2 + sign * h * dy;
|
|
150
|
-
const cy = (y0 + y1) / 2 - sign * h * dx;
|
|
151
|
-
const deg = (v) => v * 180 / Math.PI;
|
|
152
|
-
const start = deg(Math.atan2(y0 - cy, x0 - cx));
|
|
153
|
-
let sweepDeg = deg(Math.atan2(y1 - cy, x1 - cx)) - start;
|
|
154
|
-
if (sweep && sweepDeg <= 0) sweepDeg += 360;
|
|
155
|
-
if (!sweep && sweepDeg >= 0) sweepDeg -= 360;
|
|
156
|
-
return {
|
|
157
|
-
c: "A",
|
|
158
|
-
cx,
|
|
159
|
-
cy,
|
|
160
|
-
r,
|
|
161
|
-
startDeg: start,
|
|
162
|
-
sweepDeg,
|
|
163
|
-
x: x1,
|
|
164
|
-
y: y1
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
/** Parse an SVG `d` string (or relative corner segment) into absolute
|
|
168
|
-
* `PathCommand[]`. Supports M L H V C S Q T A Z; `pen` seeds relative
|
|
169
|
-
* commands when parsing a mid-path segment. */
|
|
170
|
-
function parsePath(d, penX = 0, penY = 0) {
|
|
171
|
-
const tokens = d.match(TOKEN) ?? [];
|
|
172
|
-
const out = [];
|
|
173
|
-
let i = 0;
|
|
174
|
-
let cmd = "";
|
|
175
|
-
let px = penX;
|
|
176
|
-
let py = penY;
|
|
177
|
-
let sx = penX;
|
|
178
|
-
let sy = penY;
|
|
179
|
-
const num = () => {
|
|
180
|
-
const t = tokens[i++];
|
|
181
|
-
const n = Number(t);
|
|
182
|
-
if (!Number.isFinite(n)) throw new Error(`smooth-corners: bad path token '${t}' in '${d}'`);
|
|
183
|
-
return n;
|
|
184
|
-
};
|
|
185
|
-
while (i < tokens.length) {
|
|
186
|
-
const t = tokens[i];
|
|
187
|
-
if (/[a-zA-Z]/.test(t)) {
|
|
188
|
-
cmd = t;
|
|
189
|
-
i++;
|
|
190
|
-
if (cmd === "Z" || cmd === "z") {
|
|
191
|
-
out.push({ c: "Z" });
|
|
192
|
-
px = sx;
|
|
193
|
-
py = sy;
|
|
194
|
-
continue;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
if (!cmd) throw new Error(`smooth-corners: path data missing command: '${d}'`);
|
|
198
|
-
const rel = cmd === cmd.toLowerCase();
|
|
199
|
-
const upper = cmd.toUpperCase();
|
|
200
|
-
if (ARITY[upper] === void 0) throw new Error(`smooth-corners: unsupported path command '${cmd}'`);
|
|
201
|
-
if (upper === "S" || upper === "Q" || upper === "T") throw new Error(`smooth-corners: '${upper}' commands are not supported`);
|
|
202
|
-
switch (upper) {
|
|
203
|
-
case "M": {
|
|
204
|
-
const x = num() + (rel ? px : 0);
|
|
205
|
-
const y = num() + (rel ? py : 0);
|
|
206
|
-
out.push({
|
|
207
|
-
c: "M",
|
|
208
|
-
x,
|
|
209
|
-
y
|
|
210
|
-
});
|
|
211
|
-
px = sx = x;
|
|
212
|
-
py = sy = y;
|
|
213
|
-
cmd = rel ? "l" : "L";
|
|
214
|
-
break;
|
|
215
|
-
}
|
|
216
|
-
case "L": {
|
|
217
|
-
const x = num() + (rel ? px : 0);
|
|
218
|
-
const y = num() + (rel ? py : 0);
|
|
219
|
-
out.push({
|
|
220
|
-
c: "L",
|
|
221
|
-
x,
|
|
222
|
-
y
|
|
223
|
-
});
|
|
224
|
-
px = x;
|
|
225
|
-
py = y;
|
|
226
|
-
break;
|
|
227
|
-
}
|
|
228
|
-
case "H": {
|
|
229
|
-
const x = num() + (rel ? px : 0);
|
|
230
|
-
out.push({
|
|
231
|
-
c: "L",
|
|
232
|
-
x,
|
|
233
|
-
y: py
|
|
234
|
-
});
|
|
235
|
-
px = x;
|
|
236
|
-
break;
|
|
237
|
-
}
|
|
238
|
-
case "V": {
|
|
239
|
-
const y = num() + (rel ? py : 0);
|
|
240
|
-
out.push({
|
|
241
|
-
c: "L",
|
|
242
|
-
x: px,
|
|
243
|
-
y
|
|
244
|
-
});
|
|
245
|
-
py = y;
|
|
246
|
-
break;
|
|
247
|
-
}
|
|
248
|
-
case "C": {
|
|
249
|
-
const x1 = num() + (rel ? px : 0);
|
|
250
|
-
const y1 = num() + (rel ? py : 0);
|
|
251
|
-
const x2 = num() + (rel ? px : 0);
|
|
252
|
-
const y2 = num() + (rel ? py : 0);
|
|
253
|
-
const x = num() + (rel ? px : 0);
|
|
254
|
-
const y = num() + (rel ? py : 0);
|
|
255
|
-
out.push({
|
|
256
|
-
c: "C",
|
|
257
|
-
x1,
|
|
258
|
-
y1,
|
|
259
|
-
x2,
|
|
260
|
-
y2,
|
|
261
|
-
x,
|
|
262
|
-
y
|
|
263
|
-
});
|
|
264
|
-
px = x;
|
|
265
|
-
py = y;
|
|
266
|
-
break;
|
|
267
|
-
}
|
|
268
|
-
case "A": {
|
|
269
|
-
const rx = num();
|
|
270
|
-
const ry = num();
|
|
271
|
-
const rot = num();
|
|
272
|
-
const fa = num();
|
|
273
|
-
const fs = num();
|
|
274
|
-
const x = num() + (rel ? px : 0);
|
|
275
|
-
const y = num() + (rel ? py : 0);
|
|
276
|
-
const arc = arcToCenter(px, py, rx, ry, rot, fa, fs, x, y);
|
|
277
|
-
if (arc) out.push(arc);
|
|
278
|
-
else out.push({
|
|
279
|
-
c: "L",
|
|
280
|
-
x,
|
|
281
|
-
y
|
|
282
|
-
});
|
|
283
|
-
px = x;
|
|
284
|
-
py = y;
|
|
285
|
-
break;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
return out;
|
|
290
|
-
}
|
|
291
|
-
function lisseCornerSeg(corner, radius, budget, orient, pen) {
|
|
292
|
-
const out = ft(corner.curve)({
|
|
293
|
-
cornerRadius: radius,
|
|
294
|
-
smoothing: corner.smoothing,
|
|
295
|
-
exponent: corner.exponent,
|
|
296
|
-
preserveSmoothing: corner.preserveSmoothing,
|
|
297
|
-
roundingAndSmoothingBudget: budget
|
|
298
|
-
});
|
|
299
|
-
return {
|
|
300
|
-
p: out.p,
|
|
301
|
-
cmds: segmentCommands(out.pathSegment(orient), pen)
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
function cornerCmds(corner, normalized, orient, pen, w, h) {
|
|
305
|
-
if (corner.curve === "continuous") return continuousCorner(w, h, normalized.radius, normalized.roundingAndSmoothingBudget, orient);
|
|
306
|
-
return lisseCornerSeg(corner, normalized.radius, normalized.roundingAndSmoothingBudget, orient, pen);
|
|
307
|
-
}
|
|
308
|
-
var RECT = [
|
|
309
|
-
{
|
|
310
|
-
c: "M",
|
|
311
|
-
x: 0,
|
|
312
|
-
y: 0
|
|
313
|
-
},
|
|
314
|
-
{
|
|
315
|
-
c: "L",
|
|
316
|
-
x: 0,
|
|
317
|
-
y: 0
|
|
318
|
-
},
|
|
319
|
-
{
|
|
320
|
-
c: "L",
|
|
321
|
-
x: 0,
|
|
322
|
-
y: 0
|
|
323
|
-
},
|
|
324
|
-
{
|
|
325
|
-
c: "L",
|
|
326
|
-
x: 0,
|
|
327
|
-
y: 0
|
|
328
|
-
},
|
|
329
|
-
{ c: "Z" }
|
|
330
|
-
];
|
|
331
|
-
/** Absolute command list for the smooth-cornered rect. When no corner uses
|
|
332
|
-
* `continuous`, delegates to `@lisse/core` `generatePath` (keeping its
|
|
333
|
-
* capsule/blend fast paths) and parses the result; otherwise stitches
|
|
334
|
-
* per-corner segments itself (per-corner mixing with `continuous`). */
|
|
335
|
-
function generateCommands(width, height, options) {
|
|
336
|
-
if (width <= 0 || height <= 0) return RECT;
|
|
337
|
-
const corners = resolveOptions(options);
|
|
338
|
-
if (!(corners.topLeft.curve === "continuous" || corners.topRight.curve === "continuous" || corners.bottomRight.curve === "continuous" || corners.bottomLeft.curve === "continuous")) return parsePath(ot(width, height, lisseOptions(corners)));
|
|
339
|
-
const normalized = st({
|
|
340
|
-
topLeftCornerRadius: corners.topLeft.radius,
|
|
341
|
-
topRightCornerRadius: corners.topRight.radius,
|
|
342
|
-
bottomRightCornerRadius: corners.bottomRight.radius,
|
|
343
|
-
bottomLeftCornerRadius: corners.bottomLeft.radius,
|
|
344
|
-
width,
|
|
345
|
-
height
|
|
346
|
-
});
|
|
347
|
-
const emit = (corner, n, orient, entryX, entryY) => cornerCmds(corner, n, orient, {
|
|
348
|
-
x: entryX,
|
|
349
|
-
y: entryY
|
|
350
|
-
}, width, height);
|
|
351
|
-
const pTL = previewP(corners.topLeft, normalized.topLeft, "TL", width, height);
|
|
352
|
-
const pTR = previewP(corners.topRight, normalized.topRight, "TR", width, height);
|
|
353
|
-
const pBR = previewP(corners.bottomRight, normalized.bottomRight, "BR", width, height);
|
|
354
|
-
const pBL = previewP(corners.bottomLeft, normalized.bottomLeft, "BL", width, height);
|
|
355
|
-
const out = [{
|
|
356
|
-
c: "M",
|
|
357
|
-
x: pTL,
|
|
358
|
-
y: 0
|
|
359
|
-
}];
|
|
360
|
-
out.push({
|
|
361
|
-
c: "L",
|
|
362
|
-
x: width - pTR,
|
|
363
|
-
y: 0
|
|
364
|
-
});
|
|
365
|
-
const tr = emit(corners.topRight, normalized.topRight, "TR", width - pTR, 0);
|
|
366
|
-
out.push(...tr.cmds);
|
|
367
|
-
out.push({
|
|
368
|
-
c: "L",
|
|
369
|
-
x: width,
|
|
370
|
-
y: height - pBR
|
|
371
|
-
});
|
|
372
|
-
const br = emit(corners.bottomRight, normalized.bottomRight, "BR", width, height - pBR);
|
|
373
|
-
out.push(...br.cmds);
|
|
374
|
-
out.push({
|
|
375
|
-
c: "L",
|
|
376
|
-
x: pBL,
|
|
377
|
-
y: height
|
|
378
|
-
});
|
|
379
|
-
const bl = emit(corners.bottomLeft, normalized.bottomLeft, "BL", pBL, height);
|
|
380
|
-
out.push(...bl.cmds);
|
|
381
|
-
out.push({
|
|
382
|
-
c: "L",
|
|
383
|
-
x: 0,
|
|
384
|
-
y: pTL
|
|
385
|
-
});
|
|
386
|
-
const tl = emit(corners.topLeft, normalized.topLeft, "TL", 0, pTL);
|
|
387
|
-
out.push(...tl.cmds);
|
|
388
|
-
out.push({ c: "Z" });
|
|
389
|
-
return out;
|
|
390
|
-
}
|
|
391
|
-
/** A corner's tangent distance without emitting commands (cheap for
|
|
392
|
-
* continuous; re-runs the lisse builder for other curves — called once per
|
|
393
|
-
* frame per corner, acceptable). */
|
|
394
|
-
function previewP(corner, n, orient, w, h) {
|
|
395
|
-
return cornerCmds(corner, n, orient, {
|
|
396
|
-
x: 0,
|
|
397
|
-
y: 0
|
|
398
|
-
}, w, h).p;
|
|
399
|
-
}
|
|
400
|
-
function lisseOptions(corners) {
|
|
401
|
-
const { topLeft: a, topRight: b, bottomRight: c, bottomLeft: d } = corners;
|
|
402
|
-
if (a.radius === b.radius && a.radius === c.radius && a.radius === d.radius && a.curve === b.curve && a.curve === c.curve && a.curve === d.curve && a.smoothing === b.smoothing && a.smoothing === c.smoothing && a.smoothing === d.smoothing && a.exponent === b.exponent && a.exponent === c.exponent && a.exponent === d.exponent && a.preserveSmoothing === b.preserveSmoothing && a.preserveSmoothing === c.preserveSmoothing && a.preserveSmoothing === d.preserveSmoothing) return {
|
|
403
|
-
radius: a.radius,
|
|
404
|
-
curve: a.curve,
|
|
405
|
-
smoothing: a.smoothing,
|
|
406
|
-
exponent: a.exponent,
|
|
407
|
-
preserveSmoothing: a.preserveSmoothing
|
|
408
|
-
};
|
|
409
|
-
const per = (c) => ({
|
|
410
|
-
radius: c.radius,
|
|
411
|
-
curve: c.curve,
|
|
412
|
-
smoothing: c.smoothing,
|
|
413
|
-
exponent: c.exponent,
|
|
414
|
-
preserveSmoothing: c.preserveSmoothing
|
|
415
|
-
});
|
|
416
|
-
return {
|
|
417
|
-
topLeft: per(a),
|
|
418
|
-
topRight: per(b),
|
|
419
|
-
bottomRight: per(c),
|
|
420
|
-
bottomLeft: per(d)
|
|
421
|
-
};
|
|
422
|
-
}
|
|
423
|
-
var f = (n) => Math.round(n * 1e4) / 1e4;
|
|
424
|
-
/** Serialize commands back to an SVG `d` (web `clip-path`, debug/tests). */
|
|
425
|
-
function commandsToD(cmds) {
|
|
426
|
-
const parts = [];
|
|
427
|
-
for (const c of cmds) switch (c.c) {
|
|
428
|
-
case "M":
|
|
429
|
-
parts.push(`M ${f(c.x)} ${f(c.y)}`);
|
|
430
|
-
break;
|
|
431
|
-
case "L":
|
|
432
|
-
parts.push(`L ${f(c.x)} ${f(c.y)}`);
|
|
433
|
-
break;
|
|
434
|
-
case "C":
|
|
435
|
-
parts.push(`C ${f(c.x1)} ${f(c.y1)} ${f(c.x2)} ${f(c.y2)} ${f(c.x)} ${f(c.y)}`);
|
|
436
|
-
break;
|
|
437
|
-
case "A":
|
|
438
|
-
parts.push(`A ${f(c.r)} ${f(c.r)} 0 ${Math.abs(c.sweepDeg) > 180 ? 1 : 0} ${c.sweepDeg >= 0 ? 1 : 0} ${f(c.x)} ${f(c.y)}`);
|
|
439
|
-
break;
|
|
440
|
-
case "Z": parts.push("Z");
|
|
441
|
-
}
|
|
442
|
-
return parts.join(" ");
|
|
443
|
-
}
|
|
444
|
-
/** `d` for the smooth-cornered rect — Lisse's own string when no
|
|
445
|
-
* `continuous` corner is involved (byte-identical to upstream, incl.
|
|
446
|
-
* capsule/blend fast paths), our serialization otherwise. */
|
|
447
|
-
function smoothPathD(width, height, options) {
|
|
448
|
-
const corners = resolveOptions(options);
|
|
449
|
-
if (!(corners.topLeft.curve === "continuous" || corners.topRight.curve === "continuous" || corners.bottomRight.curve === "continuous" || corners.bottomLeft.curve === "continuous") && width > 0 && height > 0) return ot(width, height, lisseOptions(corners));
|
|
450
|
-
return commandsToD(generateCommands(width, height, options));
|
|
451
|
-
}
|
|
452
|
-
//#endregion
|
|
453
|
-
export { commandsToD, generateCommands, parsePath, smoothPathD };
|