@pixerate/editor 0.96.0 → 0.98.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/THIRD_PARTY_NOTICES.md +4 -2
- package/dist/animation-editor/index.cjs +55 -53
- package/dist/animation-editor/index.cjs.map +1 -1
- package/dist/animation-editor/index.d.cts +3 -2
- package/dist/animation-editor/index.d.ts +3 -2
- package/dist/animation-editor/index.js +11 -9
- package/dist/animation-editor/index.js.map +1 -1
- package/dist/chunk-DWGZUSES.cjs +694 -0
- package/dist/chunk-DWGZUSES.cjs.map +1 -0
- package/dist/chunk-GX332W2C.js +181 -0
- package/dist/chunk-GX332W2C.js.map +1 -0
- package/dist/{chunk-7MD7C6XQ.cjs → chunk-JF5PXN7W.cjs} +96 -744
- package/dist/chunk-JF5PXN7W.cjs.map +1 -0
- package/dist/chunk-KKREERP2.js +694 -0
- package/dist/chunk-KKREERP2.js.map +1 -0
- package/dist/chunk-MUUXNRU4.cjs +181 -0
- package/dist/chunk-MUUXNRU4.cjs.map +1 -0
- package/dist/{chunk-KFTQ2PKP.js → chunk-WIR377F6.js} +1001 -61
- package/dist/chunk-WIR377F6.js.map +1 -0
- package/dist/{chunk-T422YCHR.cjs → chunk-WT6ZAWJP.cjs} +1023 -83
- package/dist/chunk-WT6ZAWJP.cjs.map +1 -0
- package/dist/{chunk-4JLB2USO.js → chunk-YGZNGDIT.js} +45 -693
- package/dist/chunk-YGZNGDIT.js.map +1 -0
- package/dist/image-editor/index.cjs +1519 -360
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +378 -5
- package/dist/image-editor/index.d.ts +378 -5
- package/dist/image-editor/index.js +1244 -85
- package/dist/image-editor/index.js.map +1 -1
- package/dist/raster/index.cjs +25 -2
- package/dist/raster/index.cjs.map +1 -1
- package/dist/raster/index.d.cts +143 -4
- package/dist/raster/index.d.ts +143 -4
- package/dist/raster/index.js +25 -2
- package/dist/{svg-ymShkNtu.d.cts → svg-C9r284x8.d.cts} +6 -9
- package/dist/{svg-Dh17jCyA.d.ts → svg-MVKBqwD4.d.ts} +6 -9
- package/dist/types-CwMPoRMU.d.cts +40 -0
- package/dist/types-CwMPoRMU.d.ts +40 -0
- package/dist/vector/index.cjs +490 -554
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +154 -292
- package/dist/vector/index.d.ts +154 -292
- package/dist/vector/index.js +91 -155
- package/dist/vector/index.js.map +1 -1
- package/dist/warp-B8rAguzs.d.ts +165 -0
- package/dist/warp-nYs2DPrx.d.cts +165 -0
- package/package.json +1 -1
- package/skills/pixerate-image-editor/SKILL.md +49 -3
- package/dist/chunk-4JLB2USO.js.map +0 -1
- package/dist/chunk-7MD7C6XQ.cjs.map +0 -1
- package/dist/chunk-KFTQ2PKP.js.map +0 -1
- package/dist/chunk-T422YCHR.cjs.map +0 -1
|
@@ -28,6 +28,32 @@ import {
|
|
|
28
28
|
transformBezierPath,
|
|
29
29
|
trimSegments
|
|
30
30
|
} from "./chunk-YCSFS3GK.js";
|
|
31
|
+
import {
|
|
32
|
+
IDENTITY_MATRIX,
|
|
33
|
+
WARP_STYLES,
|
|
34
|
+
WARP_STYLE_LABELS,
|
|
35
|
+
applyMatrix,
|
|
36
|
+
clampMeshCount,
|
|
37
|
+
decomposeRigid,
|
|
38
|
+
evalWarpMesh,
|
|
39
|
+
evenKnots,
|
|
40
|
+
fitWarpMesh,
|
|
41
|
+
identityWarpMesh,
|
|
42
|
+
invertMatrix,
|
|
43
|
+
isIdentityMatrix,
|
|
44
|
+
isValidWarpMesh,
|
|
45
|
+
lerpVec2,
|
|
46
|
+
mapWarpMeshPoints,
|
|
47
|
+
matrixRotation,
|
|
48
|
+
multiplyMatrices,
|
|
49
|
+
resizeWarpMesh,
|
|
50
|
+
rotateMatrix,
|
|
51
|
+
scaleMatrix,
|
|
52
|
+
translateMatrix,
|
|
53
|
+
warpMeshColumns,
|
|
54
|
+
warpMeshRows,
|
|
55
|
+
warpPresetMesh
|
|
56
|
+
} from "./chunk-KKREERP2.js";
|
|
31
57
|
import {
|
|
32
58
|
mixColorsOklab,
|
|
33
59
|
oklabToRgb,
|
|
@@ -2001,573 +2027,6 @@ function mapBezierPath(path, f, tolerance = 0.1, options = {}) {
|
|
|
2001
2027
|
}
|
|
2002
2028
|
|
|
2003
2029
|
// src/vector/warp.ts
|
|
2004
|
-
var VECTOR_WARP_STYLES = [
|
|
2005
|
-
"arc",
|
|
2006
|
-
"arcLower",
|
|
2007
|
-
"arcUpper",
|
|
2008
|
-
"arch",
|
|
2009
|
-
"bulge",
|
|
2010
|
-
"shellLower",
|
|
2011
|
-
"shellUpper",
|
|
2012
|
-
"flag",
|
|
2013
|
-
"wave",
|
|
2014
|
-
"fish",
|
|
2015
|
-
"rise",
|
|
2016
|
-
"fisheye",
|
|
2017
|
-
"inflate",
|
|
2018
|
-
"squeeze",
|
|
2019
|
-
"twist"
|
|
2020
|
-
];
|
|
2021
|
-
var VECTOR_WARP_STYLE_LABELS = {
|
|
2022
|
-
arc: "Arc",
|
|
2023
|
-
arcLower: "Arc Lower",
|
|
2024
|
-
arcUpper: "Arc Upper",
|
|
2025
|
-
arch: "Arch",
|
|
2026
|
-
bulge: "Bulge",
|
|
2027
|
-
shellLower: "Shell Lower",
|
|
2028
|
-
shellUpper: "Shell Upper",
|
|
2029
|
-
flag: "Flag",
|
|
2030
|
-
wave: "Wave",
|
|
2031
|
-
fish: "Fish",
|
|
2032
|
-
rise: "Rise",
|
|
2033
|
-
fisheye: "Fisheye",
|
|
2034
|
-
inflate: "Inflate",
|
|
2035
|
-
squeeze: "Squeeze",
|
|
2036
|
-
twist: "Twist"
|
|
2037
|
-
};
|
|
2038
|
-
function restGrid() {
|
|
2039
|
-
return [0, 1, 2, 3].map((j) => [0, 1, 2, 3].map((i) => [i / 3, j / 3]));
|
|
2040
|
-
}
|
|
2041
|
-
function edgeArc(y, b, up, h) {
|
|
2042
|
-
if (Math.abs(b) < 1e-9) return [0, 1, 2, 3].map((i) => [i / 3, y]);
|
|
2043
|
-
const th = Math.abs(b) * Math.PI;
|
|
2044
|
-
const k = 4 / 3 * Math.tan(th / 4) * 0.5 / Math.sin(th / 2);
|
|
2045
|
-
const s = b > 0 === up ? -1 : 1;
|
|
2046
|
-
const c = Math.cos(th / 2);
|
|
2047
|
-
const n = Math.sin(th / 2);
|
|
2048
|
-
const dy = s * k * n / h;
|
|
2049
|
-
return [
|
|
2050
|
-
[0, y],
|
|
2051
|
-
[k * c, y + dy],
|
|
2052
|
-
[1 - k * c, y + dy],
|
|
2053
|
-
[1, y]
|
|
2054
|
-
];
|
|
2055
|
-
}
|
|
2056
|
-
function arcGrid(b, h) {
|
|
2057
|
-
if (Math.abs(b) < 1e-9) return restGrid();
|
|
2058
|
-
const up = b > 0;
|
|
2059
|
-
const th = Math.abs(b) * Math.PI;
|
|
2060
|
-
const r = 0.5 / Math.sin(th / 2);
|
|
2061
|
-
const k = 4 / 3 * Math.tan(th / 4);
|
|
2062
|
-
const s = up ? -1 : 1;
|
|
2063
|
-
const cy = up ? h + r * Math.cos(th / 2) : -r * Math.cos(th / 2);
|
|
2064
|
-
return [0, 1, 2, 3].map((j) => {
|
|
2065
|
-
const v2 = j / 3;
|
|
2066
|
-
const big = r + h * (up ? 1 - v2 : v2);
|
|
2067
|
-
const at2 = (a) => [0.5 + big * Math.sin(a), cy + s * big * Math.cos(a)];
|
|
2068
|
-
const tangent2 = (a) => [Math.cos(a), -s * Math.sin(a)];
|
|
2069
|
-
const p0 = at2(-th / 2);
|
|
2070
|
-
const p3 = at2(th / 2);
|
|
2071
|
-
const t0 = tangent2(-th / 2);
|
|
2072
|
-
const t1 = tangent2(th / 2);
|
|
2073
|
-
const l = k * big;
|
|
2074
|
-
const pts = [p0, [p0[0] + l * t0[0], p0[1] + l * t0[1]], [p3[0] - l * t1[0], p3[1] - l * t1[1]], p3];
|
|
2075
|
-
return pts.map((p) => [p[0], p[1] / h]);
|
|
2076
|
-
});
|
|
2077
|
-
}
|
|
2078
|
-
function blendRows(top, bottom) {
|
|
2079
|
-
return [0, 1, 2, 3].map((j) => {
|
|
2080
|
-
const t = j / 3;
|
|
2081
|
-
return [0, 1, 2, 3].map((i) => [top[i][0] + (bottom[i][0] - top[i][0]) * t, top[i][1] + (bottom[i][1] - top[i][1]) * t]);
|
|
2082
|
-
});
|
|
2083
|
-
}
|
|
2084
|
-
var INNER = [
|
|
2085
|
-
[1, 1, -1, -1],
|
|
2086
|
-
[1, 2, 1, -1],
|
|
2087
|
-
[2, 1, -1, 1],
|
|
2088
|
-
[2, 2, 1, 1]
|
|
2089
|
-
];
|
|
2090
|
-
function vectorWarpPresetGrid(style, b, hd, vd, vertical, aspect) {
|
|
2091
|
-
const h = vertical ? 1 / aspect : aspect;
|
|
2092
|
-
if (vertical) [hd, vd] = [vd, hd];
|
|
2093
|
-
let g = restGrid();
|
|
2094
|
-
switch (style) {
|
|
2095
|
-
case "arc":
|
|
2096
|
-
g = arcGrid(b, h);
|
|
2097
|
-
break;
|
|
2098
|
-
case "arch":
|
|
2099
|
-
g = [0, 1, 2, 3].map((j) => edgeArc(j / 3, b, true, h));
|
|
2100
|
-
break;
|
|
2101
|
-
case "bulge":
|
|
2102
|
-
g = blendRows(edgeArc(0, b, true, h), edgeArc(1, b, false, h));
|
|
2103
|
-
break;
|
|
2104
|
-
case "arcLower":
|
|
2105
|
-
g = blendRows(g[0], edgeArc(1, b, false, h));
|
|
2106
|
-
break;
|
|
2107
|
-
case "arcUpper":
|
|
2108
|
-
g = blendRows(edgeArc(0, b, true, h), g[3]);
|
|
2109
|
-
break;
|
|
2110
|
-
// The bulging edge and the outer points of the row next to it come from Arc (bent the other
|
|
2111
|
-
// way for Shell Lower); the rest stays put.
|
|
2112
|
-
case "shellLower": {
|
|
2113
|
-
const a = arcGrid(-b, h);
|
|
2114
|
-
g[3] = a[3];
|
|
2115
|
-
g[2][0] = a[2][0];
|
|
2116
|
-
g[2][3] = a[2][3];
|
|
2117
|
-
break;
|
|
2118
|
-
}
|
|
2119
|
-
case "shellUpper": {
|
|
2120
|
-
const a = arcGrid(b, h);
|
|
2121
|
-
g[0] = a[0];
|
|
2122
|
-
g[1][0] = a[1][0];
|
|
2123
|
-
g[1][3] = a[1][3];
|
|
2124
|
-
break;
|
|
2125
|
-
}
|
|
2126
|
-
case "flag":
|
|
2127
|
-
for (const row of g) {
|
|
2128
|
-
row[1][1] -= 2 * b;
|
|
2129
|
-
row[2][1] += 2 * b;
|
|
2130
|
-
}
|
|
2131
|
-
break;
|
|
2132
|
-
case "wave":
|
|
2133
|
-
for (const row of g.slice(1, 3)) {
|
|
2134
|
-
row[1][1] += 4 / 3 * b;
|
|
2135
|
-
row[2][1] -= 4 / 3 * b;
|
|
2136
|
-
}
|
|
2137
|
-
break;
|
|
2138
|
-
case "fish":
|
|
2139
|
-
[-2, -2 / 3, 2 / 3, 2].forEach((f, j) => {
|
|
2140
|
-
g[j][1][1] += f * b;
|
|
2141
|
-
g[j][2][1] -= f * b;
|
|
2142
|
-
});
|
|
2143
|
-
break;
|
|
2144
|
-
case "rise":
|
|
2145
|
-
for (const row of g) {
|
|
2146
|
-
row[0][1] += 2 * b;
|
|
2147
|
-
row[1][1] += 2 * b;
|
|
2148
|
-
}
|
|
2149
|
-
break;
|
|
2150
|
-
case "fisheye":
|
|
2151
|
-
for (const [j, i, dx, dy] of INNER) {
|
|
2152
|
-
g[j][i][0] += dx * 2 * b / 3;
|
|
2153
|
-
g[j][i][1] += dy * 2 * b / 3;
|
|
2154
|
-
}
|
|
2155
|
-
break;
|
|
2156
|
-
// Edge midpoints move out (Inflate) or the sides in (Squeeze) by b/3, the inner points by b/9.
|
|
2157
|
-
case "inflate":
|
|
2158
|
-
case "squeeze": {
|
|
2159
|
-
const s = style === "inflate" ? 1 : -1;
|
|
2160
|
-
for (const p of g[0].slice(1, 3)) p[1] -= b / 3;
|
|
2161
|
-
for (const p of g[3].slice(1, 3)) p[1] += b / 3;
|
|
2162
|
-
for (const row of g.slice(1, 3)) {
|
|
2163
|
-
row[0][0] -= s * b / 3;
|
|
2164
|
-
row[3][0] += s * b / 3;
|
|
2165
|
-
}
|
|
2166
|
-
for (const [j, i, dx, dy] of INNER) {
|
|
2167
|
-
g[j][i][0] += s * dx * b / 9;
|
|
2168
|
-
g[j][i][1] += dy * b / 9;
|
|
2169
|
-
}
|
|
2170
|
-
break;
|
|
2171
|
-
}
|
|
2172
|
-
// The inner points turn round the centre (the other way for a negative bend).
|
|
2173
|
-
case "twist": {
|
|
2174
|
-
const a = Math.abs(b);
|
|
2175
|
-
if (b >= 0) {
|
|
2176
|
-
g[1][1][0] += a;
|
|
2177
|
-
g[1][2][1] += a;
|
|
2178
|
-
g[2][1][1] -= a;
|
|
2179
|
-
g[2][2][0] -= a;
|
|
2180
|
-
} else {
|
|
2181
|
-
g[1][1][1] += a;
|
|
2182
|
-
g[1][2][0] -= a;
|
|
2183
|
-
g[2][1][0] += a;
|
|
2184
|
-
g[2][2][1] -= a;
|
|
2185
|
-
}
|
|
2186
|
-
break;
|
|
2187
|
-
}
|
|
2188
|
-
}
|
|
2189
|
-
if (vd !== 0) {
|
|
2190
|
-
const moved = (row, s) => {
|
|
2191
|
-
const m = [(row[0][0] + row[3][0]) / 2, (row[0][1] + row[3][1]) / 2];
|
|
2192
|
-
return row.map((p) => [m[0] + (p[0] - m[0]) * s - p[0], m[1] + (p[1] - m[1]) * s - p[1]]);
|
|
2193
|
-
};
|
|
2194
|
-
const d0 = moved(g[0], 1 - vd);
|
|
2195
|
-
const d3 = moved(g[3], 1 + vd);
|
|
2196
|
-
g.forEach((row, j) => {
|
|
2197
|
-
const t = j / 3;
|
|
2198
|
-
row.forEach((p, i) => {
|
|
2199
|
-
p[0] += d0[i][0] + (d3[i][0] - d0[i][0]) * t;
|
|
2200
|
-
p[1] += d0[i][1] + (d3[i][1] - d0[i][1]) * t;
|
|
2201
|
-
});
|
|
2202
|
-
});
|
|
2203
|
-
}
|
|
2204
|
-
if (hd !== 0) {
|
|
2205
|
-
for (let i = 0; i < 4; i++) {
|
|
2206
|
-
const s = 1 + hd * (2 * i / 3 - 1);
|
|
2207
|
-
const m = [(g[0][i][0] + g[3][i][0]) / 2, (g[0][i][1] + g[3][i][1]) / 2];
|
|
2208
|
-
for (const row of g) row[i] = [m[0] + (row[i][0] - m[0]) * s, m[1] + (row[i][1] - m[1]) * s];
|
|
2209
|
-
}
|
|
2210
|
-
}
|
|
2211
|
-
if (vertical) g = [0, 1, 2, 3].map((j) => [0, 1, 2, 3].map((i) => [g[i][j][1], g[i][j][0]]));
|
|
2212
|
-
return g;
|
|
2213
|
-
}
|
|
2214
|
-
function bernstein(t) {
|
|
2215
|
-
const s = 1 - t;
|
|
2216
|
-
return [s * s * s, 3 * s * s * t, 3 * s * t * t, t * t * t];
|
|
2217
|
-
}
|
|
2218
|
-
var lerp3 = (a, b, t) => ({ x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t });
|
|
2219
|
-
function splitCubic(p, t) {
|
|
2220
|
-
const a = lerp3(p[0], p[1], t);
|
|
2221
|
-
const b = lerp3(p[1], p[2], t);
|
|
2222
|
-
const c = lerp3(p[2], p[3], t);
|
|
2223
|
-
const d = lerp3(a, b, t);
|
|
2224
|
-
const e = lerp3(b, c, t);
|
|
2225
|
-
return [p[0], a, d, lerp3(d, e, t), e, c, p[3]];
|
|
2226
|
-
}
|
|
2227
|
-
var BERN_INV = [
|
|
2228
|
-
[1, 0, 0, 0],
|
|
2229
|
-
[-5 / 6, 3, -1.5, 1 / 3],
|
|
2230
|
-
[1 / 3, -1.5, 3, -5 / 6],
|
|
2231
|
-
[0, 0, 0, 1]
|
|
2232
|
-
];
|
|
2233
|
-
var pct = (v2) => typeof v2 === "number" && Number.isFinite(v2) ? Math.min(1, Math.max(-1, v2 / 100)) : 0;
|
|
2234
|
-
function vectorWarpPresetMesh(preset, bounds) {
|
|
2235
|
-
if (!VECTOR_WARP_STYLES.includes(preset.style)) return null;
|
|
2236
|
-
const { x, y, width: w, height: h } = bounds;
|
|
2237
|
-
if (!(w > 0 && h > 0)) return null;
|
|
2238
|
-
const b = pct(preset.bend);
|
|
2239
|
-
const hd = pct(preset.horizontal);
|
|
2240
|
-
const vd = pct(preset.vertical);
|
|
2241
|
-
if (b === 0 && hd === 0 && vd === 0) return null;
|
|
2242
|
-
const grid = vectorWarpPresetGrid(preset.style, b, hd, vd, preset.orientation === "vertical", h / w);
|
|
2243
|
-
return { us: [0, 1], vs: [0, 1], points: grid.flat().map((p) => ({ x: x + p[0] * w, y: y + p[1] * h })) };
|
|
2244
|
-
}
|
|
2245
|
-
var vectorMeshColumns = (m) => 3 * (m.us.length - 1) + 1;
|
|
2246
|
-
var vectorMeshRows = (m) => 3 * (m.vs.length - 1) + 1;
|
|
2247
|
-
function isValidVectorMesh(m) {
|
|
2248
|
-
if (!m || typeof m !== "object") return false;
|
|
2249
|
-
const { us, vs, points } = m;
|
|
2250
|
-
const knots = (k) => Array.isArray(k) && k.length >= 2 && k.length <= 65 && k[0] === 0 && k[k.length - 1] === 1 && k.every((v2, i) => typeof v2 === "number" && (i === 0 || v2 > k[i - 1]));
|
|
2251
|
-
if (!knots(us) || !knots(vs) || !Array.isArray(points)) return false;
|
|
2252
|
-
return points.length === (3 * (us.length - 1) + 1) * (3 * (vs.length - 1) + 1) && points.every((p) => !!p && Number.isFinite(p.x) && Number.isFinite(p.y));
|
|
2253
|
-
}
|
|
2254
|
-
function fitVectorMesh(f, us, vs) {
|
|
2255
|
-
const pc = us.length - 1;
|
|
2256
|
-
const pr = vs.length - 1;
|
|
2257
|
-
const nx = 3 * pc + 1;
|
|
2258
|
-
const points = new Array((3 * pr + 1) * nx);
|
|
2259
|
-
for (let pj = 0; pj < pr; pj++) {
|
|
2260
|
-
for (let pi = 0; pi < pc; pi++) {
|
|
2261
|
-
const s = [0, 1, 2, 3].map(
|
|
2262
|
-
(j) => [0, 1, 2, 3].map((i) => f(us[pi] + (us[pi + 1] - us[pi]) * i / 3, vs[pj] + (vs[pj + 1] - vs[pj]) * j / 3))
|
|
2263
|
-
);
|
|
2264
|
-
for (let j = 0; j < 4; j++) {
|
|
2265
|
-
for (let i = 0; i < 4; i++) {
|
|
2266
|
-
let x = 0;
|
|
2267
|
-
let y = 0;
|
|
2268
|
-
for (let a = 0; a < 4; a++) {
|
|
2269
|
-
for (let b = 0; b < 4; b++) {
|
|
2270
|
-
const k = BERN_INV[j][a] * BERN_INV[i][b];
|
|
2271
|
-
x += k * s[a][b].x;
|
|
2272
|
-
y += k * s[a][b].y;
|
|
2273
|
-
}
|
|
2274
|
-
}
|
|
2275
|
-
points[(3 * pj + j) * nx + 3 * pi + i] = { x, y };
|
|
2276
|
-
}
|
|
2277
|
-
}
|
|
2278
|
-
}
|
|
2279
|
-
}
|
|
2280
|
-
return { us: us.slice(), vs: vs.slice(), points };
|
|
2281
|
-
}
|
|
2282
|
-
var evenKnots = (n) => Array.from({ length: n + 1 }, (_, i) => i / n);
|
|
2283
|
-
var clampCount = (n) => Math.min(64, Math.max(1, Math.round(Number.isFinite(n) ? n : 1)));
|
|
2284
|
-
function vectorIdentityMesh(bounds, columns = 1, rows = 1) {
|
|
2285
|
-
return fitVectorMesh((s, t) => ({ x: bounds.x + s * bounds.width, y: bounds.y + t * bounds.height }), evenKnots(clampCount(columns)), evenKnots(clampCount(rows)));
|
|
2286
|
-
}
|
|
2287
|
-
function locate(knots, s) {
|
|
2288
|
-
const n = knots.length - 1;
|
|
2289
|
-
let i = 0;
|
|
2290
|
-
while (i + 1 < n && s > knots[i + 1]) i++;
|
|
2291
|
-
const w = knots[i + 1] - knots[i];
|
|
2292
|
-
return [i, w > 0 ? (s - knots[i]) / w : 0];
|
|
2293
|
-
}
|
|
2294
|
-
function evalVectorMesh(m, s, t) {
|
|
2295
|
-
const [pi, a] = locate(m.us, s);
|
|
2296
|
-
const [pj, b] = locate(m.vs, t);
|
|
2297
|
-
const ba = bernstein(a);
|
|
2298
|
-
const bb = bernstein(b);
|
|
2299
|
-
const nx = vectorMeshColumns(m);
|
|
2300
|
-
let x = 0;
|
|
2301
|
-
let y = 0;
|
|
2302
|
-
for (let j = 0; j < 4; j++) {
|
|
2303
|
-
for (let i = 0; i < 4; i++) {
|
|
2304
|
-
const p = m.points[(3 * pj + j) * nx + 3 * pi + i];
|
|
2305
|
-
const k = ba[i] * bb[j];
|
|
2306
|
-
x += p.x * k;
|
|
2307
|
-
y += p.y * k;
|
|
2308
|
-
}
|
|
2309
|
-
}
|
|
2310
|
-
return { x, y };
|
|
2311
|
-
}
|
|
2312
|
-
function transposeMesh(m) {
|
|
2313
|
-
const nx = vectorMeshColumns(m);
|
|
2314
|
-
const ny = vectorMeshRows(m);
|
|
2315
|
-
const points = new Array(nx * ny);
|
|
2316
|
-
for (let j = 0; j < ny; j++) for (let i = 0; i < nx; i++) points[i * ny + j] = m.points[j * nx + i];
|
|
2317
|
-
return { us: m.vs.slice(), vs: m.us.slice(), points };
|
|
2318
|
-
}
|
|
2319
|
-
function splitVectorMeshU(m, s) {
|
|
2320
|
-
const [pi, a] = locate(m.us, s);
|
|
2321
|
-
if (!(a >= 0.01 && a <= 0.99)) return null;
|
|
2322
|
-
const nx = vectorMeshColumns(m);
|
|
2323
|
-
const ny = vectorMeshRows(m);
|
|
2324
|
-
const points = [];
|
|
2325
|
-
for (let j = 0; j < ny; j++) {
|
|
2326
|
-
const row = m.points.slice(j * nx, (j + 1) * nx);
|
|
2327
|
-
points.push(...row.slice(0, 3 * pi), ...splitCubic(row.slice(3 * pi, 3 * pi + 4), a), ...row.slice(3 * pi + 4));
|
|
2328
|
-
}
|
|
2329
|
-
const us = m.us.slice();
|
|
2330
|
-
us.splice(pi + 1, 0, Math.min(1, Math.max(0, s)));
|
|
2331
|
-
return { us, vs: m.vs.slice(), points };
|
|
2332
|
-
}
|
|
2333
|
-
function splitVectorMeshV(m, t) {
|
|
2334
|
-
const out = splitVectorMeshU(transposeMesh(m), t);
|
|
2335
|
-
return out && transposeMesh(out);
|
|
2336
|
-
}
|
|
2337
|
-
function removeVectorMeshSplitU(m, k) {
|
|
2338
|
-
if (k <= 0 || k + 1 >= m.us.length) return null;
|
|
2339
|
-
const a = (m.us[k] - m.us[k - 1]) / (m.us[k + 1] - m.us[k - 1]);
|
|
2340
|
-
const nx = vectorMeshColumns(m);
|
|
2341
|
-
const ny = vectorMeshRows(m);
|
|
2342
|
-
const c0 = 3 * (k - 1);
|
|
2343
|
-
const points = [];
|
|
2344
|
-
for (let j = 0; j < ny; j++) {
|
|
2345
|
-
const row = m.points.slice(j * nx, (j + 1) * nx);
|
|
2346
|
-
const [p0, q1, r2, p3] = [row[c0], row[c0 + 1], row[c0 + 5], row[c0 + 6]];
|
|
2347
|
-
const p1 = { x: (q1.x - (1 - a) * p0.x) / a, y: (q1.y - (1 - a) * p0.y) / a };
|
|
2348
|
-
const p2 = { x: (r2.x - a * p3.x) / (1 - a), y: (r2.y - a * p3.y) / (1 - a) };
|
|
2349
|
-
points.push(...row.slice(0, c0), p0, p1, p2, p3, ...row.slice(c0 + 7));
|
|
2350
|
-
}
|
|
2351
|
-
const us = m.us.slice();
|
|
2352
|
-
us.splice(k, 1);
|
|
2353
|
-
return { us, vs: m.vs.slice(), points };
|
|
2354
|
-
}
|
|
2355
|
-
function removeVectorMeshSplitV(m, k) {
|
|
2356
|
-
const out = removeVectorMeshSplitU(transposeMesh(m), k);
|
|
2357
|
-
return out && transposeMesh(out);
|
|
2358
|
-
}
|
|
2359
|
-
function mapVectorMeshPoints(m, f) {
|
|
2360
|
-
return { us: m.us.slice(), vs: m.vs.slice(), points: m.points.map((p) => f(p)) };
|
|
2361
|
-
}
|
|
2362
|
-
function resizeVectorMesh(m, columns, rows) {
|
|
2363
|
-
const cols = clampCount(columns);
|
|
2364
|
-
const rws = clampCount(rows);
|
|
2365
|
-
if (m.us.length - 1 === cols && m.vs.length - 1 === rws) return m;
|
|
2366
|
-
const us = evenKnots(cols);
|
|
2367
|
-
const vs = evenKnots(rws);
|
|
2368
|
-
const has = (list, v2) => list.some((k) => Math.abs(k - v2) < 1e-12);
|
|
2369
|
-
if (m.us.every((u) => has(us, u)) && m.vs.every((v2) => has(vs, v2))) {
|
|
2370
|
-
let out = m;
|
|
2371
|
-
for (const u of us) if (!has(out.us, u)) out = splitVectorMeshU(out, u) ?? out;
|
|
2372
|
-
for (const v2 of vs) if (!has(out.vs, v2)) out = splitVectorMeshV(out, v2) ?? out;
|
|
2373
|
-
return out;
|
|
2374
|
-
}
|
|
2375
|
-
return fitVectorMesh((s, t) => evalVectorMesh(m, s, t), us, vs);
|
|
2376
|
-
}
|
|
2377
|
-
function vectorMeshControlBounds(m) {
|
|
2378
|
-
let minX = Infinity;
|
|
2379
|
-
let minY = Infinity;
|
|
2380
|
-
let maxX = -Infinity;
|
|
2381
|
-
let maxY = -Infinity;
|
|
2382
|
-
for (const p of m.points) {
|
|
2383
|
-
minX = Math.min(minX, p.x);
|
|
2384
|
-
minY = Math.min(minY, p.y);
|
|
2385
|
-
maxX = Math.max(maxX, p.x);
|
|
2386
|
-
maxY = Math.max(maxY, p.y);
|
|
2387
|
-
}
|
|
2388
|
-
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
2389
|
-
}
|
|
2390
|
-
function vectorMeshParamAt(m, p) {
|
|
2391
|
-
const n = 48;
|
|
2392
|
-
let best = { s: 0.5, t: 0.5, d: Infinity };
|
|
2393
|
-
for (let j = 0; j <= n; j++) {
|
|
2394
|
-
for (let i = 0; i <= n; i++) {
|
|
2395
|
-
const q2 = evalVectorMesh(m, i / n, j / n);
|
|
2396
|
-
const d = (q2.x - p.x) ** 2 + (q2.y - p.y) ** 2;
|
|
2397
|
-
if (d < best.d) best = { s: i / n, t: j / n, d };
|
|
2398
|
-
}
|
|
2399
|
-
}
|
|
2400
|
-
let { s, t } = best;
|
|
2401
|
-
for (let k = 0; k < 12; k++) {
|
|
2402
|
-
const h = 1e-5;
|
|
2403
|
-
const q2 = evalVectorMesh(m, s, t);
|
|
2404
|
-
const qs = evalVectorMesh(m, s + h, t);
|
|
2405
|
-
const qt = evalVectorMesh(m, s, t + h);
|
|
2406
|
-
const a = (qs.x - q2.x) / h;
|
|
2407
|
-
const b = (qt.x - q2.x) / h;
|
|
2408
|
-
const c = (qs.y - q2.y) / h;
|
|
2409
|
-
const d = (qt.y - q2.y) / h;
|
|
2410
|
-
const det = a * d - b * c;
|
|
2411
|
-
if (Math.abs(det) < 1e-12) break;
|
|
2412
|
-
const ex = p.x - q2.x;
|
|
2413
|
-
const ey = p.y - q2.y;
|
|
2414
|
-
s = Math.min(1, Math.max(0, s + (d * ex - b * ey) / det));
|
|
2415
|
-
t = Math.min(1, Math.max(0, t + (a * ey - c * ex) / det));
|
|
2416
|
-
}
|
|
2417
|
-
const q = evalVectorMesh(m, s, t);
|
|
2418
|
-
return { s, t, distance: Math.hypot(q.x - p.x, q.y - p.y) };
|
|
2419
|
-
}
|
|
2420
|
-
function smoothLines(m, i0, i1, j0, j1) {
|
|
2421
|
-
const nx = vectorMeshColumns(m);
|
|
2422
|
-
i1 = Math.min(i1, nx);
|
|
2423
|
-
j1 = Math.min(j1, vectorMeshRows(m));
|
|
2424
|
-
const triples = [];
|
|
2425
|
-
for (let a = 1; a < m.us.length - 1; a++) {
|
|
2426
|
-
if (3 * a >= i0 && 3 * a < i1)
|
|
2427
|
-
for (let j = j0; j < j1; j++) triples.push([j * nx + 3 * a - 1, j * nx + 3 * a, j * nx + 3 * a + 1, m.us[a] - m.us[a - 1], m.us[a + 1] - m.us[a]]);
|
|
2428
|
-
}
|
|
2429
|
-
for (let b = 1; b < m.vs.length - 1; b++) {
|
|
2430
|
-
if (3 * b >= j0 && 3 * b < j1)
|
|
2431
|
-
for (let i = i0; i < i1; i++) triples.push([(3 * b - 1) * nx + i, 3 * b * nx + i, (3 * b + 1) * nx + i, m.vs[b] - m.vs[b - 1], m.vs[b + 1] - m.vs[b]]);
|
|
2432
|
-
}
|
|
2433
|
-
for (const [l, c, r, hl, hr] of triples) {
|
|
2434
|
-
const pl = m.points[l];
|
|
2435
|
-
const pc = m.points[c];
|
|
2436
|
-
const pr = m.points[r];
|
|
2437
|
-
const tx = ((pc.x - pl.x) / hl + (pr.x - pc.x) / hr) / 2;
|
|
2438
|
-
const ty = ((pc.y - pl.y) / hl + (pr.y - pc.y) / hr) / 2;
|
|
2439
|
-
m.points[l] = { x: pc.x - tx * hl, y: pc.y - ty * hl };
|
|
2440
|
-
m.points[r] = { x: pc.x + tx * hr, y: pc.y + ty * hr };
|
|
2441
|
-
}
|
|
2442
|
-
}
|
|
2443
|
-
function dragVectorMeshPoint(base, index, d) {
|
|
2444
|
-
if (index < 0 || index >= base.points.length || !Number.isFinite(d.x) || !Number.isFinite(d.y)) return base;
|
|
2445
|
-
const out = { us: base.us.slice(), vs: base.vs.slice(), points: base.points.slice() };
|
|
2446
|
-
const nx = vectorMeshColumns(base);
|
|
2447
|
-
const ny = vectorMeshRows(base);
|
|
2448
|
-
const i = index % nx;
|
|
2449
|
-
const j = Math.floor(index / nx);
|
|
2450
|
-
const shift = (ii, jj, v2) => {
|
|
2451
|
-
if (ii < 0 || jj < 0 || ii >= nx || jj >= ny) return;
|
|
2452
|
-
const p = out.points[jj * nx + ii];
|
|
2453
|
-
out.points[jj * nx + ii] = { x: p.x + v2.x, y: p.y + v2.y };
|
|
2454
|
-
};
|
|
2455
|
-
const span = (knots, k) => k > 0 && k + 1 < knots.length ? [knots[k] - knots[k - 1], knots[k + 1] - knots[k]] : null;
|
|
2456
|
-
const ri = i % 3;
|
|
2457
|
-
const rj = j % 3;
|
|
2458
|
-
if (ri === 0 && rj === 0) {
|
|
2459
|
-
for (let dj = -1; dj <= 1; dj++) for (let di = -1; di <= 1; di++) shift(i + di, j + dj, d);
|
|
2460
|
-
} else if (ri === 0) {
|
|
2461
|
-
for (let di = -1; di <= 1; di++) shift(i + di, j, d);
|
|
2462
|
-
const sp = span(base.vs, Math.floor(j / 3) + (rj === 2 ? 1 : 0));
|
|
2463
|
-
if (sp) {
|
|
2464
|
-
const [other, k] = rj === 1 ? [j - 2, sp[0] / sp[1]] : [j + 2, sp[1] / sp[0]];
|
|
2465
|
-
for (let di = -1; di <= 1; di++) shift(i + di, other, { x: -d.x * k, y: -d.y * k });
|
|
2466
|
-
}
|
|
2467
|
-
} else if (rj === 0) {
|
|
2468
|
-
for (let dj = -1; dj <= 1; dj++) shift(i, j + dj, d);
|
|
2469
|
-
const sp = span(base.us, Math.floor(i / 3) + (ri === 2 ? 1 : 0));
|
|
2470
|
-
if (sp) {
|
|
2471
|
-
const [other, k] = ri === 1 ? [i - 2, sp[0] / sp[1]] : [i + 2, sp[1] / sp[0]];
|
|
2472
|
-
for (let dj = -1; dj <= 1; dj++) shift(other, j + dj, { x: -d.x * k, y: -d.y * k });
|
|
2473
|
-
}
|
|
2474
|
-
} else shift(i, j, d);
|
|
2475
|
-
return out;
|
|
2476
|
-
}
|
|
2477
|
-
function pullVectorMesh(base, s, t, d) {
|
|
2478
|
-
const BORDER_ZONE = 0.12;
|
|
2479
|
-
const REACH = 1.8;
|
|
2480
|
-
if (!Number.isFinite(d.x) || !Number.isFinite(d.y)) return base;
|
|
2481
|
-
const m = { us: base.us.slice(), vs: base.vs.slice(), points: base.points.slice() };
|
|
2482
|
-
const cols = m.us.length - 1;
|
|
2483
|
-
const rows = m.vs.length - 1;
|
|
2484
|
-
const [pi, a] = locate(m.us, s);
|
|
2485
|
-
const [pj, b] = locate(m.vs, t);
|
|
2486
|
-
const ba = bernstein(a);
|
|
2487
|
-
const bb = bernstein(b);
|
|
2488
|
-
const nx = vectorMeshColumns(m);
|
|
2489
|
-
const ny = vectorMeshRows(m);
|
|
2490
|
-
const anchor = (ai, aj) => base.points[3 * aj * nx + 3 * ai] ?? { x: 0, y: 0 };
|
|
2491
|
-
const at0 = evalVectorMesh(base, s, t);
|
|
2492
|
-
const target = { x: at0.x + d.x, y: at0.y + d.y };
|
|
2493
|
-
let size = 1;
|
|
2494
|
-
for (const k of ["x", "y"]) {
|
|
2495
|
-
const vals = [anchor(pi, pj)[k], anchor(pi + 1, pj)[k], anchor(pi, pj + 1)[k], anchor(pi + 1, pj + 1)[k]];
|
|
2496
|
-
size = Math.max(size, Math.max(...vals) - Math.min(...vals));
|
|
2497
|
-
}
|
|
2498
|
-
const radius = REACH * size;
|
|
2499
|
-
const innerW = (ba[1] + ba[2]) * (bb[1] + bb[2]);
|
|
2500
|
-
const interior = Math.min(1, Math.max(0, innerW / 0.5625));
|
|
2501
|
-
const toBorder = Math.min(s, 1 - s, t, 1 - t);
|
|
2502
|
-
const nearBorder = Math.min(1, Math.max(0, 1 - toBorder / BORDER_ZONE));
|
|
2503
|
-
const meshCorner = (ai, aj) => (ai === 0 || ai === cols) && (aj === 0 || aj === rows);
|
|
2504
|
-
const onBorder = (ai, aj) => ai === 0 || ai === cols || aj === 0 || aj === rows;
|
|
2505
|
-
const reach = (ai, aj, wa, wb) => meshCorner(ai, aj) ? 0 : wa * wb * (onBorder(ai, aj) ? nearBorder : 1);
|
|
2506
|
-
const corner = [
|
|
2507
|
-
[pi, pj, reach(pi, pj, ba[0] + ba[1], bb[0] + bb[1])],
|
|
2508
|
-
[pi + 1, pj, reach(pi + 1, pj, ba[2] + ba[3], bb[0] + bb[1])],
|
|
2509
|
-
[pi, pj + 1, reach(pi, pj + 1, ba[0] + ba[1], bb[2] + bb[3])],
|
|
2510
|
-
[pi + 1, pj + 1, reach(pi + 1, pj + 1, ba[2] + ba[3], bb[2] + bb[3])]
|
|
2511
|
-
];
|
|
2512
|
-
const share = new Array((cols + 1) * (rows + 1)).fill(0);
|
|
2513
|
-
for (let aj = 0; aj <= rows; aj++) {
|
|
2514
|
-
for (let ai = 0; ai <= cols; ai++) {
|
|
2515
|
-
const p = anchor(ai, aj);
|
|
2516
|
-
const x = Math.min(1, Math.max(0, Math.hypot(p.x - at0.x, p.y - at0.y) / radius));
|
|
2517
|
-
const fall = 0.5 * (1 + Math.cos(Math.PI * x));
|
|
2518
|
-
const edge = meshCorner(ai, aj) ? 0 : onBorder(ai, aj) ? nearBorder : 1;
|
|
2519
|
-
share[aj * (cols + 1) + ai] = fall * edge;
|
|
2520
|
-
}
|
|
2521
|
-
}
|
|
2522
|
-
for (const [ai, aj, w] of corner) share[aj * (cols + 1) + ai] = Math.max(share[aj * (cols + 1) + ai], (1 - interior) * w);
|
|
2523
|
-
const move = (idx, k, v2) => {
|
|
2524
|
-
const p = m.points[idx];
|
|
2525
|
-
m.points[idx] = { x: p.x + v2.x * k, y: p.y + v2.y * k };
|
|
2526
|
-
};
|
|
2527
|
-
for (let j = 0; j < ny; j++) {
|
|
2528
|
-
for (let i = 0; i < nx; i++) {
|
|
2529
|
-
const ai = Math.min(cols, Math.floor((i + 1) / 3));
|
|
2530
|
-
const aj = Math.min(rows, Math.floor((j + 1) / 3));
|
|
2531
|
-
move(j * nx + i, share[aj * (cols + 1) + ai], d);
|
|
2532
|
-
}
|
|
2533
|
-
}
|
|
2534
|
-
let norm = 0;
|
|
2535
|
-
for (const j of [1, 2]) for (const i of [1, 2]) norm += (ba[i] * bb[j]) ** 2;
|
|
2536
|
-
const cornerNorm = corner.reduce((acc, c) => acc + c[2] * c[2], 0);
|
|
2537
|
-
const innerPart = cornerNorm > 1e-12 ? Math.min(1, innerW / 0.15) : 1;
|
|
2538
|
-
const edgeHandles = [];
|
|
2539
|
-
for (const k of [1, 2]) {
|
|
2540
|
-
if (pi === 0) edgeHandles.push([(3 * pj + k) * nx + 3 * pi, ba[0] * bb[k]]);
|
|
2541
|
-
if (pi + 1 === cols) edgeHandles.push([(3 * pj + k) * nx + 3 * pi + 3, ba[3] * bb[k]]);
|
|
2542
|
-
if (pj === 0) edgeHandles.push([3 * pj * nx + 3 * pi + k, ba[k] * bb[0]]);
|
|
2543
|
-
if (pj + 1 === rows) edgeHandles.push([(3 * pj + 3) * nx + 3 * pi + k, ba[k] * bb[3]]);
|
|
2544
|
-
}
|
|
2545
|
-
const edgeNorm = edgeHandles.reduce((acc, e) => acc + e[1] * e[1], 0);
|
|
2546
|
-
const edgePart = edgeNorm > 1e-12 ? nearBorder : 0;
|
|
2547
|
-
const innerShare = (1 - edgePart) * innerPart;
|
|
2548
|
-
const cornerShare = (1 - edgePart) * (1 - innerPart);
|
|
2549
|
-
for (let iter = 0; iter < 60; iter++) {
|
|
2550
|
-
const now = evalVectorMesh(m, s, t);
|
|
2551
|
-
const rem = { x: target.x - now.x, y: target.y - now.y };
|
|
2552
|
-
if (Math.hypot(rem.x, rem.y) < 1e-9) break;
|
|
2553
|
-
if (innerShare > 0 && norm > 0) for (const j of [1, 2]) for (const i of [1, 2]) move((3 * pj + j) * nx + 3 * pi + i, ba[i] * bb[j] / norm * innerShare, rem);
|
|
2554
|
-
if (edgePart > 0) for (const [idx, w] of edgeHandles) move(idx, w / edgeNorm * edgePart, rem);
|
|
2555
|
-
if (cornerShare > 0 && cornerNorm > 0) {
|
|
2556
|
-
for (const [ai, aj, w] of corner) {
|
|
2557
|
-
const k = w / cornerNorm * cornerShare;
|
|
2558
|
-
for (let dj = -1; dj <= 1; dj++) {
|
|
2559
|
-
for (let di = -1; di <= 1; di++) {
|
|
2560
|
-
const i = 3 * ai + di;
|
|
2561
|
-
const j = 3 * aj + dj;
|
|
2562
|
-
if (i >= 0 && j >= 0 && i < nx && j < ny) move(j * nx + i, k, rem);
|
|
2563
|
-
}
|
|
2564
|
-
}
|
|
2565
|
-
}
|
|
2566
|
-
}
|
|
2567
|
-
for (let k = 0; k < 3; k++) smoothLines(m, Math.max(0, 3 * pi - 3), 3 * pi + 7, Math.max(0, 3 * pj - 3), 3 * pj + 7);
|
|
2568
|
-
}
|
|
2569
|
-
return m;
|
|
2570
|
-
}
|
|
2571
2030
|
function polylineAt(pts) {
|
|
2572
2031
|
const acc = [0];
|
|
2573
2032
|
for (let i = 1; i < pts.length; i++) acc.push(acc[i - 1] + Math.hypot(pts[i].x - pts[i - 1].x, pts[i].y - pts[i - 1].y));
|
|
@@ -2578,7 +2037,7 @@ function polylineAt(pts) {
|
|
|
2578
2037
|
let i = 1;
|
|
2579
2038
|
while (i < acc.length - 1 && acc[i] < L) i++;
|
|
2580
2039
|
const seg = acc[i] - acc[i - 1];
|
|
2581
|
-
return
|
|
2040
|
+
return lerpVec2(pts[i - 1], pts[i], seg > 0 ? (L - acc[i - 1]) / seg : 0);
|
|
2582
2041
|
};
|
|
2583
2042
|
}
|
|
2584
2043
|
function sampleSubpath(sp, per = 24) {
|
|
@@ -2590,10 +2049,10 @@ function sampleSubpath(sp, per = 24) {
|
|
|
2590
2049
|
const c = [{ x: a.x, y: a.y }, a.out ?? a, b.in ?? b, { x: b.x, y: b.y }];
|
|
2591
2050
|
for (let k = 0; k < per; k++) {
|
|
2592
2051
|
const t = k / per;
|
|
2593
|
-
const ab =
|
|
2594
|
-
const bc =
|
|
2595
|
-
const cd =
|
|
2596
|
-
out.push(
|
|
2052
|
+
const ab = lerpVec2(c[0], c[1], t);
|
|
2053
|
+
const bc = lerpVec2(c[1], c[2], t);
|
|
2054
|
+
const cd = lerpVec2(c[2], c[3], t);
|
|
2055
|
+
out.push(lerpVec2(lerpVec2(ab, bc, t), lerpVec2(bc, cd, t), t));
|
|
2597
2056
|
}
|
|
2598
2057
|
}
|
|
2599
2058
|
return out;
|
|
@@ -2651,11 +2110,11 @@ function vectorMeshFromOutline(sp, columns = 4, rows = 4) {
|
|
|
2651
2110
|
y: (1 - t) * T.y + t * B.y + (1 - s) * L.y + s * R.y - ((1 - s) * (1 - t) * p00.y + s * (1 - t) * p10.y + (1 - s) * t * p01.y + s * t * p11.y)
|
|
2652
2111
|
};
|
|
2653
2112
|
};
|
|
2654
|
-
return
|
|
2113
|
+
return fitWarpMesh(coons, evenKnots(clampMeshCount(columns)), evenKnots(clampMeshCount(rows)));
|
|
2655
2114
|
}
|
|
2656
2115
|
function vectorMeshOutline(m) {
|
|
2657
|
-
const nx =
|
|
2658
|
-
const ny =
|
|
2116
|
+
const nx = warpMeshColumns(m);
|
|
2117
|
+
const ny = warpMeshRows(m);
|
|
2659
2118
|
const pt2 = (i, j) => m.points[j * nx + i];
|
|
2660
2119
|
const runs = [];
|
|
2661
2120
|
for (let i = 0; i + 3 < nx; i += 3) runs.push([pt2(i, 0), pt2(i + 1, 0), pt2(i + 2, 0), pt2(i + 3, 0)]);
|
|
@@ -2668,31 +2127,6 @@ function vectorMeshOutline(m) {
|
|
|
2668
2127
|
});
|
|
2669
2128
|
return { closed: true, anchors };
|
|
2670
2129
|
}
|
|
2671
|
-
function vectorMeshEditPoints(m) {
|
|
2672
|
-
const nx = vectorMeshColumns(m);
|
|
2673
|
-
const ny = vectorMeshRows(m);
|
|
2674
|
-
const anchors = [];
|
|
2675
|
-
const handles = [];
|
|
2676
|
-
for (let j = 0; j < ny; j++) {
|
|
2677
|
-
for (let i = 0; i < nx; i++) {
|
|
2678
|
-
const ri = i % 3;
|
|
2679
|
-
const rj = j % 3;
|
|
2680
|
-
if (ri === 0 && rj === 0) anchors.push(j * nx + i);
|
|
2681
|
-
else if (ri === 0) handles.push({ index: j * nx + i, anchor: (rj === 1 ? j - 1 : j + 1) * nx + i });
|
|
2682
|
-
else if (rj === 0) handles.push({ index: j * nx + i, anchor: j * nx + (ri === 1 ? i - 1 : i + 1) });
|
|
2683
|
-
}
|
|
2684
|
-
}
|
|
2685
|
-
return { anchors, handles };
|
|
2686
|
-
}
|
|
2687
|
-
function vectorMeshGridCurves(m) {
|
|
2688
|
-
const nx = vectorMeshColumns(m);
|
|
2689
|
-
const ny = vectorMeshRows(m);
|
|
2690
|
-
const pt2 = (i, j) => m.points[j * nx + i];
|
|
2691
|
-
const out = [];
|
|
2692
|
-
for (let j = 0; j < ny; j += 3) for (let i = 0; i + 3 < nx; i += 3) out.push([pt2(i, j), pt2(i + 1, j), pt2(i + 2, j), pt2(i + 3, j)]);
|
|
2693
|
-
for (let i = 0; i < nx; i += 3) for (let j = 0; j + 3 < ny; j += 3) out.push([pt2(i, j), pt2(i, j + 1), pt2(i, j + 2), pt2(i, j + 3)]);
|
|
2694
|
-
return out;
|
|
2695
|
-
}
|
|
2696
2130
|
|
|
2697
2131
|
// src/vector/appearance.ts
|
|
2698
2132
|
var VECTOR_EFFECT_DEFAULTS = {
|
|
@@ -2819,7 +2253,7 @@ var VECTOR_EFFECT_PARAM_SPECS = {
|
|
|
2819
2253
|
key: "style",
|
|
2820
2254
|
label: "Warp",
|
|
2821
2255
|
kind: "select",
|
|
2822
|
-
options: [...
|
|
2256
|
+
options: [...WARP_STYLES.map((value) => ({ value, label: WARP_STYLE_LABELS[value] })), { value: "mesh", label: "Mesh" }]
|
|
2823
2257
|
},
|
|
2824
2258
|
{ key: "bend", label: "Bend %", kind: "number", min: -100, max: 100, step: 1, slider: true },
|
|
2825
2259
|
{ key: "horizontal", label: "Horizontal distortion %", kind: "number", min: -100, max: 100, step: 1, slider: true },
|
|
@@ -2839,16 +2273,16 @@ var VECTOR_EFFECT_PARAM_SPECS = {
|
|
|
2839
2273
|
};
|
|
2840
2274
|
var cloneMesh = (m) => ({ us: m.us.slice(), vs: m.vs.slice(), points: m.points.map((p) => ({ x: p.x, y: p.y })) });
|
|
2841
2275
|
function vectorEnvelopeMesh(params, bounds) {
|
|
2842
|
-
if (params.style === "mesh") return params.mesh ??
|
|
2843
|
-
const preset =
|
|
2844
|
-
return preset ?
|
|
2276
|
+
if (params.style === "mesh") return params.mesh ?? identityWarpMesh(bounds, params.columns, params.rows);
|
|
2277
|
+
const preset = warpPresetMesh({ style: params.style, bend: params.bend, horizontal: params.horizontal, vertical: params.vertical, orientation: params.orientation }, bounds);
|
|
2278
|
+
return preset ? resizeWarpMesh(preset, params.columns, params.rows) : identityWarpMesh(bounds, params.columns, params.rows);
|
|
2845
2279
|
}
|
|
2846
2280
|
function vectorEnvelopeMap(params, bounds) {
|
|
2847
2281
|
if (!bounds || !(bounds.width > 0 && bounds.height > 0)) return null;
|
|
2848
|
-
const mesh = params.style === "mesh" ? params.mesh :
|
|
2282
|
+
const mesh = params.style === "mesh" ? params.mesh : warpPresetMesh({ style: params.style, bend: params.bend, horizontal: params.horizontal, vertical: params.vertical, orientation: params.orientation }, bounds);
|
|
2849
2283
|
if (!mesh) return null;
|
|
2850
2284
|
const { x, y, width, height } = bounds;
|
|
2851
|
-
return (p) =>
|
|
2285
|
+
return (p) => evalWarpMesh(mesh, (p.x - x) / width, (p.y - y) / height);
|
|
2852
2286
|
}
|
|
2853
2287
|
function pathsBounds(paths) {
|
|
2854
2288
|
let minX = Infinity;
|
|
@@ -2890,12 +2324,12 @@ function normalizeVectorEffectParams(type, params, base) {
|
|
|
2890
2324
|
o.rows = Math.round(o.rows);
|
|
2891
2325
|
o.columns = Math.round(o.columns);
|
|
2892
2326
|
const given = params?.mesh;
|
|
2893
|
-
let mesh = given !== void 0 ?
|
|
2327
|
+
let mesh = given !== void 0 ? isValidWarpMesh(given) ? cloneMesh(given) : null : o.mesh;
|
|
2894
2328
|
if (o.style !== "mesh") mesh = null;
|
|
2895
2329
|
if (mesh && given !== void 0) {
|
|
2896
2330
|
o.columns = mesh.us.length - 1;
|
|
2897
2331
|
o.rows = mesh.vs.length - 1;
|
|
2898
|
-
} else if (mesh) mesh =
|
|
2332
|
+
} else if (mesh) mesh = resizeWarpMesh(mesh, o.columns, o.rows);
|
|
2899
2333
|
o.mesh = mesh;
|
|
2900
2334
|
}
|
|
2901
2335
|
return out;
|
|
@@ -3261,11 +2695,11 @@ function transformVectorEffects(effects, m, node) {
|
|
|
3261
2695
|
const axisScale = Math.abs(m[1]) < 1e-12 && Math.abs(m[2]) < 1e-12 && m[0] > 0 && m[3] > 0;
|
|
3262
2696
|
return effects.map((e) => {
|
|
3263
2697
|
if (e.type === "envelope") {
|
|
3264
|
-
if (e.params.style === "mesh") return e.params.mesh ? { ...e, params: { ...e.params, mesh:
|
|
2698
|
+
if (e.params.style === "mesh") return e.params.mesh ? { ...e, params: { ...e.params, mesh: mapWarpMeshPoints(e.params.mesh, full) } } : e;
|
|
3265
2699
|
if (axisScale || !node) return e;
|
|
3266
2700
|
const bounds = vectorEffectInputBounds(node, e.id);
|
|
3267
2701
|
if (!bounds || !vectorEnvelopeMap(e.params, bounds)) return e;
|
|
3268
|
-
return { ...e, params: { ...e.params, style: "mesh", mesh:
|
|
2702
|
+
return { ...e, params: { ...e.params, style: "mesh", mesh: mapWarpMeshPoints(vectorEnvelopeMesh(e.params, bounds), full) } };
|
|
3269
2703
|
}
|
|
3270
2704
|
if (e.type === "twist") return { ...e, params: { ...e.params, center: lin(e.params.center), angle: e.params.angle * mirror } };
|
|
3271
2705
|
if (e.type === "repeater")
|
|
@@ -3540,55 +2974,6 @@ function nearestSegment(node, p) {
|
|
|
3540
2974
|
});
|
|
3541
2975
|
return best;
|
|
3542
2976
|
}
|
|
3543
|
-
var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
|
|
3544
|
-
function multiplyMatrices(a, b) {
|
|
3545
|
-
const [a0, a1, a2, a3, a4, a5] = a;
|
|
3546
|
-
const [b0, b1, b2, b3, b4, b5] = b;
|
|
3547
|
-
return [b0 * a0 + b2 * a1, b1 * a0 + b3 * a1, b0 * a2 + b2 * a3, b1 * a2 + b3 * a3, b0 * a4 + b2 * a5 + b4, b1 * a4 + b3 * a5 + b5];
|
|
3548
|
-
}
|
|
3549
|
-
var translateMatrix = (dx, dy) => [1, 0, 0, 1, dx, dy];
|
|
3550
|
-
function scaleMatrix(sx, sy, origin = { x: 0, y: 0 }) {
|
|
3551
|
-
return [sx, 0, 0, sy, origin.x - sx * origin.x, origin.y - sy * origin.y];
|
|
3552
|
-
}
|
|
3553
|
-
function rotateMatrix(degrees, origin = { x: 0, y: 0 }) {
|
|
3554
|
-
const r = degrees * Math.PI / 180;
|
|
3555
|
-
const cos = Math.cos(r);
|
|
3556
|
-
const sin = Math.sin(r);
|
|
3557
|
-
return [cos, sin, -sin, cos, origin.x - cos * origin.x + sin * origin.y, origin.y - sin * origin.x - cos * origin.y];
|
|
3558
|
-
}
|
|
3559
|
-
function applyMatrix(m, p) {
|
|
3560
|
-
return { x: m[0] * p.x + m[2] * p.y + m[4], y: m[1] * p.x + m[3] * p.y + m[5] };
|
|
3561
|
-
}
|
|
3562
|
-
function isIdentityMatrix(m, eps = 1e-12) {
|
|
3563
|
-
return Math.abs(m[0] - 1) < eps && Math.abs(m[1]) < eps && Math.abs(m[2]) < eps && Math.abs(m[3] - 1) < eps && Math.abs(m[4]) < eps && Math.abs(m[5]) < eps;
|
|
3564
|
-
}
|
|
3565
|
-
function invertMatrix(m) {
|
|
3566
|
-
const [a, b, c, d, e, f] = m;
|
|
3567
|
-
const det = a * d - b * c;
|
|
3568
|
-
if (!det || !Number.isFinite(det)) return IDENTITY_MATRIX;
|
|
3569
|
-
return [d / det, -b / det, -c / det, a / det, (c * f - d * e) / det, (b * e - a * f) / det];
|
|
3570
|
-
}
|
|
3571
|
-
function applyMatrixLinear(m, v2) {
|
|
3572
|
-
return { x: m[0] * v2.x + m[2] * v2.y, y: m[1] * v2.x + m[3] * v2.y };
|
|
3573
|
-
}
|
|
3574
|
-
function matrixRotation(m) {
|
|
3575
|
-
const [a, b, c, d] = m;
|
|
3576
|
-
const mirrored = a * d - b * c < 0;
|
|
3577
|
-
const deg = (mirrored ? Math.atan2(-b - c, d - a) : Math.atan2(b - c, a + d)) * 180 / Math.PI;
|
|
3578
|
-
return Math.abs(deg) < 1e-9 ? 0 : deg;
|
|
3579
|
-
}
|
|
3580
|
-
function decomposeRigid(m) {
|
|
3581
|
-
const [a, b, c, d, e, f] = m;
|
|
3582
|
-
const deg = matrixRotation(m);
|
|
3583
|
-
if (deg === 0) return { rigid: IDENTITY_MATRIX, residual: m };
|
|
3584
|
-
const r = deg * Math.PI / 180;
|
|
3585
|
-
const cos = Math.cos(r);
|
|
3586
|
-
const sin = Math.sin(r);
|
|
3587
|
-
return {
|
|
3588
|
-
rigid: [cos, sin, -sin, cos, e, f],
|
|
3589
|
-
residual: [cos * a + sin * b, -sin * a + cos * b, cos * c + sin * d, -sin * c + cos * d, 0, 0]
|
|
3590
|
-
};
|
|
3591
|
-
}
|
|
3592
2977
|
function mapAnchor(a, m) {
|
|
3593
2978
|
const p = applyMatrix(m, a);
|
|
3594
2979
|
const next = { x: p.x, y: p.y };
|
|
@@ -5856,30 +5241,8 @@ export {
|
|
|
5856
5241
|
mapVectorPoints,
|
|
5857
5242
|
mapVectorSubpaths,
|
|
5858
5243
|
mapBezierPath,
|
|
5859
|
-
VECTOR_WARP_STYLES,
|
|
5860
|
-
VECTOR_WARP_STYLE_LABELS,
|
|
5861
|
-
vectorWarpPresetGrid,
|
|
5862
|
-
vectorWarpPresetMesh,
|
|
5863
|
-
vectorMeshColumns,
|
|
5864
|
-
vectorMeshRows,
|
|
5865
|
-
isValidVectorMesh,
|
|
5866
|
-
fitVectorMesh,
|
|
5867
|
-
vectorIdentityMesh,
|
|
5868
|
-
evalVectorMesh,
|
|
5869
|
-
splitVectorMeshU,
|
|
5870
|
-
splitVectorMeshV,
|
|
5871
|
-
removeVectorMeshSplitU,
|
|
5872
|
-
removeVectorMeshSplitV,
|
|
5873
|
-
mapVectorMeshPoints,
|
|
5874
|
-
resizeVectorMesh,
|
|
5875
|
-
vectorMeshControlBounds,
|
|
5876
|
-
vectorMeshParamAt,
|
|
5877
|
-
dragVectorMeshPoint,
|
|
5878
|
-
pullVectorMesh,
|
|
5879
5244
|
vectorMeshFromOutline,
|
|
5880
5245
|
vectorMeshOutline,
|
|
5881
|
-
vectorMeshEditPoints,
|
|
5882
|
-
vectorMeshGridCurves,
|
|
5883
5246
|
VECTOR_EFFECT_DEFAULTS,
|
|
5884
5247
|
VECTOR_EFFECT_LABELS,
|
|
5885
5248
|
VECTOR_EFFECT_PARAM_SPECS,
|
|
@@ -5934,17 +5297,6 @@ export {
|
|
|
5934
5297
|
vectorStrokeOutline,
|
|
5935
5298
|
hitTestVectorNodes,
|
|
5936
5299
|
nearestSegment,
|
|
5937
|
-
IDENTITY_MATRIX,
|
|
5938
|
-
multiplyMatrices,
|
|
5939
|
-
translateMatrix,
|
|
5940
|
-
scaleMatrix,
|
|
5941
|
-
rotateMatrix,
|
|
5942
|
-
applyMatrix,
|
|
5943
|
-
isIdentityMatrix,
|
|
5944
|
-
invertMatrix,
|
|
5945
|
-
applyMatrixLinear,
|
|
5946
|
-
matrixRotation,
|
|
5947
|
-
decomposeRigid,
|
|
5948
5300
|
transformVectorNode,
|
|
5949
5301
|
vectorNodeRotation,
|
|
5950
5302
|
vectorWorldMatrix,
|
|
@@ -5991,4 +5343,4 @@ export {
|
|
|
5991
5343
|
parseSvgTransform,
|
|
5992
5344
|
parseVectorSvg
|
|
5993
5345
|
};
|
|
5994
|
-
//# sourceMappingURL=chunk-
|
|
5346
|
+
//# sourceMappingURL=chunk-YGZNGDIT.js.map
|