@pixerate/editor 0.190.0 → 0.191.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/dist/{chunk-T4U4O6DS.cjs → chunk-2UR4OX3B.cjs} +6 -9
- package/dist/{chunk-M7XIC2FC.js → chunk-RQ2EM5TY.js} +333 -0
- package/dist/{chunk-7ZWLDVFH.js → chunk-TXYXF32N.js} +6 -9
- package/dist/{chunk-5UEFNX24.cjs → chunk-ZQGZWFPU.cjs} +344 -11
- package/dist/image-editor/controller.d.cts +23 -1
- package/dist/image-editor/controller.d.ts +23 -1
- package/dist/image-editor/index.cjs +1056 -896
- package/dist/image-editor/index.js +173 -13
- package/dist/image-editor/layers/panel.d.cts +1 -1
- package/dist/image-editor/layers/panel.d.ts +1 -1
- package/dist/image-editor/layers/vector-mask.d.cts +2 -2
- package/dist/image-editor/layers/vector-mask.d.ts +2 -2
- package/dist/image-editor/selection/index.d.cts +1 -0
- package/dist/image-editor/selection/index.d.ts +1 -0
- package/dist/image-editor/selection/path.d.cts +37 -0
- package/dist/image-editor/selection/path.d.ts +37 -0
- package/dist/paint-editor/index.cjs +6 -6
- package/dist/paint-editor/index.js +1 -1
- package/dist/vector/index.cjs +21 -303
- package/dist/vector/index.js +15 -297
- package/dist/vector/trace.d.cts +8 -1
- package/dist/vector/trace.d.ts +8 -1
- package/package.json +1 -1
- package/skills/pixerate-image-editor/SKILL.md +3 -1
- package/skills/pixerate-image-selection-masking/SKILL.md +6 -2
|
@@ -1,4 +1,332 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkNM3G4VQTcjs = require('./chunk-NM3G4VQT.cjs');
|
|
5
|
+
|
|
6
|
+
// src/vector/trace.ts
|
|
7
|
+
var VECTOR_TRACE_MAX_PIXELS = 4e6;
|
|
8
|
+
function signedArea(p) {
|
|
9
|
+
let a = 0;
|
|
10
|
+
for (let i = 0; i < p.length; i++) {
|
|
11
|
+
const [x0, y0] = p[i];
|
|
12
|
+
const [x1, y1] = p[(i + 1) % p.length];
|
|
13
|
+
a += x0 * y1 - x1 * y0;
|
|
14
|
+
}
|
|
15
|
+
return a / 2;
|
|
16
|
+
}
|
|
17
|
+
function pointInPoly(p, poly) {
|
|
18
|
+
let inside = false;
|
|
19
|
+
for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {
|
|
20
|
+
const [xi, yi] = poly[i];
|
|
21
|
+
const [xj, yj] = poly[j];
|
|
22
|
+
if (yi > p[1] !== yj > p[1] && p[0] < (xj - xi) * (p[1] - yi) / (yj - yi) + xi) inside = !inside;
|
|
23
|
+
}
|
|
24
|
+
return inside;
|
|
25
|
+
}
|
|
26
|
+
function vectorTraceContours(field, w, h, threshold) {
|
|
27
|
+
const gw = w + 2;
|
|
28
|
+
const gh = h + 2;
|
|
29
|
+
const val = (i, j) => i === 0 || j === 0 || i > w || j > h ? -Infinity : field[(j - 1) * w + (i - 1)];
|
|
30
|
+
const inside = (i, j) => val(i, j) >= threshold;
|
|
31
|
+
const pos = (i, j) => [i - 0.5, j - 0.5];
|
|
32
|
+
const cross = (a, b) => {
|
|
33
|
+
const va = val(a[0], a[1]);
|
|
34
|
+
const vb = val(b[0], b[1]);
|
|
35
|
+
let t;
|
|
36
|
+
if (Number.isFinite(va) && Number.isFinite(vb) && Math.abs(vb - va) > 1e-12) t = Math.min(1, Math.max(0, (threshold - va) / (vb - va)));
|
|
37
|
+
else if (Number.isFinite(va)) t = va >= threshold ? 0.5 : 0;
|
|
38
|
+
else t = vb >= threshold ? 0.5 : 1;
|
|
39
|
+
const pa = pos(a[0], a[1]);
|
|
40
|
+
const pb = pos(b[0], b[1]);
|
|
41
|
+
return [pa[0] + (pb[0] - pa[0]) * t, pa[1] + (pb[1] - pa[1]) * t];
|
|
42
|
+
};
|
|
43
|
+
const hid = (i, j) => 2 * (j * gw + i);
|
|
44
|
+
const vid = (i, j) => 2 * (j * gw + i) + 1;
|
|
45
|
+
const next = /* @__PURE__ */ new Map();
|
|
46
|
+
const point = /* @__PURE__ */ new Map();
|
|
47
|
+
for (let j = 0; j < gh - 1; j++) {
|
|
48
|
+
for (let i = 0; i < gw - 1; i++) {
|
|
49
|
+
const tl = inside(i, j);
|
|
50
|
+
const tr = inside(i + 1, j);
|
|
51
|
+
const br = inside(i + 1, j + 1);
|
|
52
|
+
const bl = inside(i, j + 1);
|
|
53
|
+
const code = +tl << 3 | +tr << 2 | +br << 1 | +bl;
|
|
54
|
+
if (code === 0 || code === 15) continue;
|
|
55
|
+
const top = hid(i, j);
|
|
56
|
+
const bottom = hid(i, j + 1);
|
|
57
|
+
const left = vid(i, j);
|
|
58
|
+
const right = vid(i + 1, j);
|
|
59
|
+
const seg = (a, b) => next.set(a, b);
|
|
60
|
+
const mean = () => (val(i, j) + val(i + 1, j) + val(i + 1, j + 1) + val(i, j + 1)) / 4;
|
|
61
|
+
switch (code) {
|
|
62
|
+
case 1:
|
|
63
|
+
seg(left, bottom);
|
|
64
|
+
break;
|
|
65
|
+
case 2:
|
|
66
|
+
seg(bottom, right);
|
|
67
|
+
break;
|
|
68
|
+
case 3:
|
|
69
|
+
seg(left, right);
|
|
70
|
+
break;
|
|
71
|
+
case 4:
|
|
72
|
+
seg(right, top);
|
|
73
|
+
break;
|
|
74
|
+
case 5:
|
|
75
|
+
if (mean() >= threshold) {
|
|
76
|
+
seg(left, top);
|
|
77
|
+
seg(right, bottom);
|
|
78
|
+
} else {
|
|
79
|
+
seg(left, bottom);
|
|
80
|
+
seg(right, top);
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
case 6:
|
|
84
|
+
seg(bottom, top);
|
|
85
|
+
break;
|
|
86
|
+
case 7:
|
|
87
|
+
seg(left, top);
|
|
88
|
+
break;
|
|
89
|
+
case 8:
|
|
90
|
+
seg(top, left);
|
|
91
|
+
break;
|
|
92
|
+
case 9:
|
|
93
|
+
seg(top, bottom);
|
|
94
|
+
break;
|
|
95
|
+
case 10:
|
|
96
|
+
if (mean() >= threshold) {
|
|
97
|
+
seg(top, right);
|
|
98
|
+
seg(bottom, left);
|
|
99
|
+
} else {
|
|
100
|
+
seg(top, left);
|
|
101
|
+
seg(bottom, right);
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
case 11:
|
|
105
|
+
seg(top, right);
|
|
106
|
+
break;
|
|
107
|
+
case 12:
|
|
108
|
+
seg(right, left);
|
|
109
|
+
break;
|
|
110
|
+
case 13:
|
|
111
|
+
seg(right, bottom);
|
|
112
|
+
break;
|
|
113
|
+
case 14:
|
|
114
|
+
seg(bottom, left);
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
const edges = [
|
|
118
|
+
[top, [i, j], [i + 1, j]],
|
|
119
|
+
[bottom, [i, j + 1], [i + 1, j + 1]],
|
|
120
|
+
[left, [i, j], [i, j + 1]],
|
|
121
|
+
[right, [i + 1, j], [i + 1, j + 1]]
|
|
122
|
+
];
|
|
123
|
+
for (const [e, a, b] of edges) if (inside(a[0], a[1]) !== inside(b[0], b[1]) && !point.has(e)) point.set(e, cross(a, b));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const out = [];
|
|
127
|
+
for (const start of [...next.keys()].sort((a, b) => a - b)) {
|
|
128
|
+
if (!next.has(start)) continue;
|
|
129
|
+
const poly = [];
|
|
130
|
+
let e = start;
|
|
131
|
+
for (; ; ) {
|
|
132
|
+
const n = next.get(e);
|
|
133
|
+
if (n === void 0) break;
|
|
134
|
+
next.delete(e);
|
|
135
|
+
const p = point.get(e);
|
|
136
|
+
if (p) poly.push(p);
|
|
137
|
+
e = n;
|
|
138
|
+
if (e === start) break;
|
|
139
|
+
}
|
|
140
|
+
if (poly.length >= 3) out.push(poly);
|
|
141
|
+
}
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
144
|
+
function squareContourCorners(ring) {
|
|
145
|
+
const n = ring.length;
|
|
146
|
+
if (n < 4) return ring;
|
|
147
|
+
const eq = (u, v) => Math.abs(u - v) < 1e-9;
|
|
148
|
+
const out = [];
|
|
149
|
+
for (let i = 0; i < n; i++) {
|
|
150
|
+
const a = ring[i];
|
|
151
|
+
const b = ring[(i + 1) % n];
|
|
152
|
+
const p = ring[(i - 1 + n) % n];
|
|
153
|
+
const q = ring[(i + 2) % n];
|
|
154
|
+
const diagonal = Math.abs(Math.abs(b[0] - a[0]) - 0.5) < 0.02 && Math.abs(Math.abs(b[1] - a[1]) - 0.5) < 0.02;
|
|
155
|
+
const wraps = i === n - 1;
|
|
156
|
+
let corner = null;
|
|
157
|
+
if (diagonal && (!wraps || out[0] === ring[0])) {
|
|
158
|
+
if (eq(p[1], a[1]) && !eq(p[0], a[0]) && eq(q[0], b[0]) && !eq(q[1], b[1])) corner = [b[0], a[1]];
|
|
159
|
+
else if (eq(p[0], a[0]) && !eq(p[1], a[1]) && eq(q[1], b[1]) && !eq(q[0], b[0])) corner = [a[0], b[1]];
|
|
160
|
+
}
|
|
161
|
+
if (!corner) {
|
|
162
|
+
out.push(a);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
out.push(corner);
|
|
166
|
+
if (wraps) out.shift();
|
|
167
|
+
else i++;
|
|
168
|
+
}
|
|
169
|
+
if (out.length < 3) return ring;
|
|
170
|
+
const m = out.length;
|
|
171
|
+
for (let k = 0; k < m; k++) {
|
|
172
|
+
const p = out[(k - 1 + m) % m];
|
|
173
|
+
const a = out[k];
|
|
174
|
+
const q = out[(k + 1) % m];
|
|
175
|
+
if (Math.abs((a[0] - p[0]) * (q[1] - a[1]) - (a[1] - p[1]) * (q[0] - a[0])) > 1e-6) return k ? [...out.slice(k), ...out.slice(0, k)] : out;
|
|
176
|
+
}
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
function loopsOf(field, w, h, threshold, tolerance, minArea, square = false) {
|
|
180
|
+
const loops = [];
|
|
181
|
+
for (const contour of vectorTraceContours(field, w, h, threshold)) {
|
|
182
|
+
const raw = square ? squareContourCorners(contour) : contour;
|
|
183
|
+
const area = signedArea(raw);
|
|
184
|
+
if (Math.abs(area) < Math.max(0, minArea)) continue;
|
|
185
|
+
const simple = _chunkNM3G4VQTcjs.simplifyRing.call(void 0, raw, Math.max(0.01, tolerance));
|
|
186
|
+
if (simple.length < 3) continue;
|
|
187
|
+
loops.push({ raw, simple, area, depth: 0 });
|
|
188
|
+
}
|
|
189
|
+
for (const l of loops) l.depth = loops.filter((o) => o !== l && Math.abs(o.area) > Math.abs(l.area) && pointInPoly(l.simple[0], o.simple)).length;
|
|
190
|
+
return loops.sort((a, b) => a.depth - b.depth || Math.abs(b.area) - Math.abs(a.area));
|
|
191
|
+
}
|
|
192
|
+
function loopSubpath(l, tolerance, roundness) {
|
|
193
|
+
if (roundness <= 0) return { closed: true, anchors: l.simple.map(([x, y]) => ({ x, y })) };
|
|
194
|
+
const cornerAngleDeg = 25 + roundness * 125;
|
|
195
|
+
const cubics = _chunkNM3G4VQTcjs.fitCubics.call(void 0, l.raw, Math.max(0.05, tolerance), {
|
|
196
|
+
closed: true,
|
|
197
|
+
cornerAngleDeg
|
|
198
|
+
});
|
|
199
|
+
if (!cubics.length) return { closed: true, anchors: l.simple.map(([x, y]) => ({ x, y })) };
|
|
200
|
+
const anchors = cubics.map((c, k) => {
|
|
201
|
+
const prev = cubics[(k - 1 + cubics.length) % cubics.length];
|
|
202
|
+
return {
|
|
203
|
+
x: c.p0[0],
|
|
204
|
+
y: c.p0[1],
|
|
205
|
+
in: { x: prev.p2[0], y: prev.p2[1] },
|
|
206
|
+
out: { x: c.p1[0], y: c.p1[1] }
|
|
207
|
+
};
|
|
208
|
+
});
|
|
209
|
+
return { closed: true, anchors };
|
|
210
|
+
}
|
|
211
|
+
function traceField(field, w, h, threshold, o) {
|
|
212
|
+
const tolerance = _nullishCoalesce(o.tolerance, () => ( 1));
|
|
213
|
+
const roundness = Math.min(1, Math.max(0, _nullishCoalesce(o.cornerRoundness, () => ( 0.5))));
|
|
214
|
+
return loopsOf(field, w, h, threshold, tolerance, _nullishCoalesce(o.minArea, () => ( 10)), o.squareCorners === true).map((l) => loopSubpath(l, tolerance, roundness));
|
|
215
|
+
}
|
|
216
|
+
function quantizeVectorTraceColors(pixels, count) {
|
|
217
|
+
const n = pixels.width * pixels.height;
|
|
218
|
+
const d = pixels.data;
|
|
219
|
+
const opaque = [];
|
|
220
|
+
for (let i = 0; i < n; i++) if (d[i * 4 + 3] >= 128) opaque.push(i);
|
|
221
|
+
const boxes = opaque.length ? [opaque] : [];
|
|
222
|
+
const range = (box, c) => {
|
|
223
|
+
let lo = 255;
|
|
224
|
+
let hi = 0;
|
|
225
|
+
for (const i of box) {
|
|
226
|
+
const v = d[i * 4 + c];
|
|
227
|
+
if (v < lo) lo = v;
|
|
228
|
+
if (v > hi) hi = v;
|
|
229
|
+
}
|
|
230
|
+
return hi - lo;
|
|
231
|
+
};
|
|
232
|
+
while (boxes.length < count) {
|
|
233
|
+
let best = -1;
|
|
234
|
+
let bestRange = 0;
|
|
235
|
+
let bestC = 0;
|
|
236
|
+
boxes.forEach((b, k) => {
|
|
237
|
+
if (b.length < 2) return;
|
|
238
|
+
for (let c = 0; c < 3; c++) {
|
|
239
|
+
const r = range(b, c);
|
|
240
|
+
if (r > bestRange) {
|
|
241
|
+
bestRange = r;
|
|
242
|
+
best = k;
|
|
243
|
+
bestC = c;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
if (best < 0) break;
|
|
248
|
+
const box = boxes[best].slice().sort((a, b) => d[a * 4 + bestC] - d[b * 4 + bestC]);
|
|
249
|
+
const key = (k) => d[box[k] * 4 + bestC];
|
|
250
|
+
const v = key(box.length >> 1);
|
|
251
|
+
let mid = box.findIndex((_, k) => key(k) >= v);
|
|
252
|
+
if (mid <= 0) mid = box.findIndex((_, k) => key(k) > v);
|
|
253
|
+
boxes.splice(best, 1, box.slice(0, mid), box.slice(mid));
|
|
254
|
+
}
|
|
255
|
+
const palette = boxes.map((b) => {
|
|
256
|
+
const s = [0, 0, 0];
|
|
257
|
+
for (const i of b) for (let c = 0; c < 3; c++) s[c] += d[i * 4 + c];
|
|
258
|
+
return [Math.round(s[0] / b.length), Math.round(s[1] / b.length), Math.round(s[2] / b.length)];
|
|
259
|
+
});
|
|
260
|
+
const index = new Int16Array(n).fill(-1);
|
|
261
|
+
const counts = palette.map(() => 0);
|
|
262
|
+
for (const i of opaque) {
|
|
263
|
+
let best = 0;
|
|
264
|
+
let bestD = Infinity;
|
|
265
|
+
palette.forEach((p, k) => {
|
|
266
|
+
const dd = (d[i * 4] - p[0]) ** 2 + (d[i * 4 + 1] - p[1]) ** 2 + (d[i * 4 + 2] - p[2]) ** 2;
|
|
267
|
+
if (dd < bestD) {
|
|
268
|
+
bestD = dd;
|
|
269
|
+
best = k;
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
index[i] = best;
|
|
273
|
+
counts[best]++;
|
|
274
|
+
}
|
|
275
|
+
return { palette, index, counts };
|
|
276
|
+
}
|
|
277
|
+
var hex = (c) => `#${c.map((v) => Math.round(v).toString(16).padStart(2, "0")).join("")}`;
|
|
278
|
+
function traceVectorImage(pixels, options = {}) {
|
|
279
|
+
const { width: w, height: h, data } = pixels;
|
|
280
|
+
if (!(w > 0 && h > 0) || data.length < w * h * 4) throw new Error("The image has no pixels (or fewer than width \xD7 height \xD7 4 values).");
|
|
281
|
+
if (w * h > VECTOR_TRACE_MAX_PIXELS) throw new Error(`The image has ${w * h} pixels; scale it down to at most ${VECTOR_TRACE_MAX_PIXELS} to trace it.`);
|
|
282
|
+
const n = w * h;
|
|
283
|
+
if ((_nullishCoalesce(options.mode, () => ( "threshold"))) === "threshold") {
|
|
284
|
+
const field = new Float32Array(n);
|
|
285
|
+
const byAlpha = options.channel === "alpha";
|
|
286
|
+
for (let i = 0; i < n; i++) {
|
|
287
|
+
const a = data[i * 4 + 3] / 255;
|
|
288
|
+
field[i] = byAlpha ? a : a * (1 - (0.2126 * data[i * 4] + 0.7152 * data[i * 4 + 1] + 0.0722 * data[i * 4 + 2]) / 255);
|
|
289
|
+
}
|
|
290
|
+
const subpaths = traceField(field, w, h, Math.min(1, Math.max(0, _nullishCoalesce(options.threshold, () => ( 0.5)))), options);
|
|
291
|
+
return subpaths.length ? [
|
|
292
|
+
{
|
|
293
|
+
id: "trace-1",
|
|
294
|
+
type: "path",
|
|
295
|
+
name: "Trace",
|
|
296
|
+
fill: _nullishCoalesce(options.color, () => ( "#000000")),
|
|
297
|
+
stroke: null,
|
|
298
|
+
fillRule: "evenodd",
|
|
299
|
+
subpaths
|
|
300
|
+
}
|
|
301
|
+
] : [];
|
|
302
|
+
}
|
|
303
|
+
const count = Math.min(32, Math.max(2, Math.round(_nullishCoalesce(options.colors, () => ( 6)))));
|
|
304
|
+
const q = quantizeVectorTraceColors(pixels, count);
|
|
305
|
+
const order = q.palette.map((_, k) => k).filter((k) => q.counts[k] > 0).sort((a, b) => q.counts[b] - q.counts[a]);
|
|
306
|
+
const rank = new Map(order.map((k, r) => [k, r]));
|
|
307
|
+
const out = [];
|
|
308
|
+
order.forEach((k, r) => {
|
|
309
|
+
const field = new Uint8Array(n);
|
|
310
|
+
for (let i = 0; i < n; i++) {
|
|
311
|
+
const ix = q.index[i];
|
|
312
|
+
field[i] = ix >= 0 && rank.get(ix) >= r ? 1 : 0;
|
|
313
|
+
}
|
|
314
|
+
const subpaths = traceField(field, w, h, 0.5, options);
|
|
315
|
+
if (subpaths.length)
|
|
316
|
+
out.push({
|
|
317
|
+
id: `trace-${out.length + 1}`,
|
|
318
|
+
type: "path",
|
|
319
|
+
name: hex(q.palette[k]),
|
|
320
|
+
fill: hex(q.palette[k]),
|
|
321
|
+
stroke: null,
|
|
322
|
+
fillRule: "evenodd",
|
|
323
|
+
subpaths
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
return out;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/text/opentype.ts
|
|
2
330
|
var fail = (message) => {
|
|
3
331
|
throw new Error(message);
|
|
4
332
|
};
|
|
@@ -310,22 +638,22 @@ function cffOutlines(view, t, numGlyphs) {
|
|
|
310
638
|
const gsubrs = cffIndex(view, strings.end).items;
|
|
311
639
|
if (!tops.items.length) fail("The font's CFF table has no Top DICT.");
|
|
312
640
|
const top = cffDict(view, tops.items[0][0], tops.items[0][1]);
|
|
313
|
-
const charStrings = cffIndex(view, base + (_nullishCoalesce(_optionalChain([top, 'access',
|
|
641
|
+
const charStrings = cffIndex(view, base + (_nullishCoalesce(_optionalChain([top, 'access', _2 => _2.get, 'call', _3 => _3(17), 'optionalAccess', _4 => _4[0]]), () => ( fail("The font's CFF table has no CharStrings."))))).items;
|
|
314
642
|
const privateOf = (dict) => {
|
|
315
643
|
const pv = dict.get(18);
|
|
316
644
|
if (!pv || pv.length < 2) return { subrs: [], defaultWidth: 0, nominalWidth: 0 };
|
|
317
645
|
const [size, off] = pv;
|
|
318
646
|
const priv = cffDict(view, base + off, base + off + size);
|
|
319
|
-
const subrsOff = _optionalChain([priv, 'access',
|
|
647
|
+
const subrsOff = _optionalChain([priv, 'access', _5 => _5.get, 'call', _6 => _6(19), 'optionalAccess', _7 => _7[0]]);
|
|
320
648
|
return {
|
|
321
649
|
subrs: subrsOff !== void 0 ? cffIndex(view, base + off + subrsOff).items : [],
|
|
322
|
-
defaultWidth: _nullishCoalesce(_optionalChain([priv, 'access',
|
|
323
|
-
nominalWidth: _nullishCoalesce(_optionalChain([priv, 'access',
|
|
650
|
+
defaultWidth: _nullishCoalesce(_optionalChain([priv, 'access', _8 => _8.get, 'call', _9 => _9(20), 'optionalAccess', _10 => _10[0]]), () => ( 0)),
|
|
651
|
+
nominalWidth: _nullishCoalesce(_optionalChain([priv, 'access', _11 => _11.get, 'call', _12 => _12(21), 'optionalAccess', _13 => _13[0]]), () => ( 0))
|
|
324
652
|
};
|
|
325
653
|
};
|
|
326
654
|
let fdFor;
|
|
327
|
-
const fdArrayOff = _optionalChain([top, 'access',
|
|
328
|
-
const fdSelectOff = _optionalChain([top, 'access',
|
|
655
|
+
const fdArrayOff = _optionalChain([top, 'access', _14 => _14.get, 'call', _15 => _15(1236), 'optionalAccess', _16 => _16[0]]);
|
|
656
|
+
const fdSelectOff = _optionalChain([top, 'access', _17 => _17.get, 'call', _18 => _18(1237), 'optionalAccess', _19 => _19[0]]);
|
|
329
657
|
if (fdArrayOff !== void 0 && fdSelectOff !== void 0) {
|
|
330
658
|
const fds = cffIndex(view, base + fdArrayOff).items.map(([a, b]) => privateOf(cffDict(view, a, b)));
|
|
331
659
|
const sel = base + fdSelectOff;
|
|
@@ -795,7 +1123,7 @@ function parseOpenTypeFont(data, options = {}) {
|
|
|
795
1123
|
if (g < 0 || g >= numGlyphs) return 0;
|
|
796
1124
|
const i = Math.min(g, numHMetrics - 1);
|
|
797
1125
|
if (i >= 0 && hmtx.offset + i * 4 + 2 <= hmtx.offset + hmtx.length) return view.getUint16(hmtx.offset + i * 4);
|
|
798
|
-
return _nullishCoalesce(_optionalChain([cffWidth, 'optionalCall',
|
|
1126
|
+
return _nullishCoalesce(_optionalChain([cffWidth, 'optionalCall', _20 => _20(g)]), () => ( 0));
|
|
799
1127
|
};
|
|
800
1128
|
const kernPairs = readKern(view, tables.get("kern"));
|
|
801
1129
|
const gpos = gposKerning(view, tables.get("GPOS"));
|
|
@@ -849,11 +1177,11 @@ function parseOpenTypeFont(data, options = {}) {
|
|
|
849
1177
|
kerning,
|
|
850
1178
|
glyphPath,
|
|
851
1179
|
getAdvanceWidth(text, fontSize, opts) {
|
|
852
|
-
return layout(text, _optionalChain([opts, 'optionalAccess',
|
|
1180
|
+
return layout(text, _optionalChain([opts, 'optionalAccess', _21 => _21.kerning]) !== false).width * fontSize / unitsPerEm;
|
|
853
1181
|
},
|
|
854
1182
|
getPath(text, x, y, fontSize, opts) {
|
|
855
1183
|
const k = fontSize / unitsPerEm;
|
|
856
|
-
const { gs, xs } = layout(text, _optionalChain([opts, 'optionalAccess',
|
|
1184
|
+
const { gs, xs } = layout(text, _optionalChain([opts, 'optionalAccess', _22 => _22.kerning]) !== false);
|
|
857
1185
|
const commands = [];
|
|
858
1186
|
gs.forEach((g, i) => {
|
|
859
1187
|
const ox = x + xs[i] * k;
|
|
@@ -925,4 +1253,9 @@ async function unwoff(view) {
|
|
|
925
1253
|
|
|
926
1254
|
|
|
927
1255
|
|
|
928
|
-
|
|
1256
|
+
|
|
1257
|
+
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
exports.VECTOR_TRACE_MAX_PIXELS = VECTOR_TRACE_MAX_PIXELS; exports.vectorTraceContours = vectorTraceContours; exports.traceField = traceField; exports.quantizeVectorTraceColors = quantizeVectorTraceColors; exports.traceVectorImage = traceVectorImage; exports.parseOpenTypeFont = parseOpenTypeFont; exports.loadOpenTypeFont = loadOpenTypeFont;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AdjustmentKind, AdjustmentLayer, AdjustmentParamsMap, Annotation, CreateAnnotationPayload, AspectRatio, CropBox, DepthMaskOptions, ExportOptions, ImageAdjustments, ImageDimensions, ImageEditorFit, ImageEditorOptions, ImageEditorState, ImageEditorTool, ImageTransform, ImagePoint, SerializedImageEditorState } from './types.cjs';
|
|
2
|
+
import { type PathToSelectionOptions, type SelectionToPathOptions } from './selection/path.cjs';
|
|
2
3
|
import { RenderOptions } from './renderer.cjs';
|
|
3
4
|
import { type BlendMode } from './blend.cjs';
|
|
4
5
|
import type { ImageHistogram } from './histogram.cjs';
|
|
@@ -921,7 +922,28 @@ export declare class ImageEditorController {
|
|
|
921
922
|
* hiding everything) or `path` (reveals inside the path given). Replaces an existing vector mask;
|
|
922
923
|
* the raster mask is kept and both apply. One undo step. Returns the vector mask.
|
|
923
924
|
*/
|
|
924
|
-
addVectorMask(id: string, from?: 'reveal-all' | 'hide-all' | 'path', path?: VectorMaskPathInput): VectorMask;
|
|
925
|
+
addVectorMask(id: string, from?: 'reveal-all' | 'hide-all' | 'path' | 'selection', path?: VectorMaskPathInput, trace?: SelectionToPathOptions): VectorMask;
|
|
926
|
+
/** The selection's outline as subpaths; throws when nothing is selected or nothing is left to trace. */
|
|
927
|
+
private traceSelection;
|
|
928
|
+
/**
|
|
929
|
+
* Make Work Path: the selection's outline as closed Bézier subpaths in document pixels, holes
|
|
930
|
+
* included (fill them even-odd), within `tolerance` px. Changes nothing. Throws without a selection.
|
|
931
|
+
*/
|
|
932
|
+
selectionToPath(options?: SelectionToPathOptions): {
|
|
933
|
+
subpaths: VectorSubpath[];
|
|
934
|
+
svg: string;
|
|
935
|
+
fillRule: 'evenodd';
|
|
936
|
+
bounds: CropBox | null;
|
|
937
|
+
anchors: number;
|
|
938
|
+
};
|
|
939
|
+
/**
|
|
940
|
+
* Make Selection: fills a path (`shape`, `subpaths` or `components`, document pixels) into a
|
|
941
|
+
* selection combined with the current one by `mode`, with `feather` px and `antiAlias`. One
|
|
942
|
+
* undo step. Returns whether anything is selected.
|
|
943
|
+
*/
|
|
944
|
+
pathToSelection(path: VectorMaskPathInput, options?: PathToSelectionOptions & {
|
|
945
|
+
mode?: SelectionMode;
|
|
946
|
+
}): boolean;
|
|
925
947
|
/** Replaces a vector mask's path (its properties are kept). One undo step. Returns the vector mask. */
|
|
926
948
|
setVectorMaskPath(id: string, path: VectorMaskPathInput): VectorMask;
|
|
927
949
|
/** Changes a vector mask's enabled, linked, inverted, density or feather (the path is kept). One undo step. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AdjustmentKind, AdjustmentLayer, AdjustmentParamsMap, Annotation, CreateAnnotationPayload, AspectRatio, CropBox, DepthMaskOptions, ExportOptions, ImageAdjustments, ImageDimensions, ImageEditorFit, ImageEditorOptions, ImageEditorState, ImageEditorTool, ImageTransform, ImagePoint, SerializedImageEditorState } from './types.js';
|
|
2
|
+
import { type PathToSelectionOptions, type SelectionToPathOptions } from './selection/path.js';
|
|
2
3
|
import { RenderOptions } from './renderer.js';
|
|
3
4
|
import { type BlendMode } from './blend.js';
|
|
4
5
|
import type { ImageHistogram } from './histogram.js';
|
|
@@ -921,7 +922,28 @@ export declare class ImageEditorController {
|
|
|
921
922
|
* hiding everything) or `path` (reveals inside the path given). Replaces an existing vector mask;
|
|
922
923
|
* the raster mask is kept and both apply. One undo step. Returns the vector mask.
|
|
923
924
|
*/
|
|
924
|
-
addVectorMask(id: string, from?: 'reveal-all' | 'hide-all' | 'path', path?: VectorMaskPathInput): VectorMask;
|
|
925
|
+
addVectorMask(id: string, from?: 'reveal-all' | 'hide-all' | 'path' | 'selection', path?: VectorMaskPathInput, trace?: SelectionToPathOptions): VectorMask;
|
|
926
|
+
/** The selection's outline as subpaths; throws when nothing is selected or nothing is left to trace. */
|
|
927
|
+
private traceSelection;
|
|
928
|
+
/**
|
|
929
|
+
* Make Work Path: the selection's outline as closed Bézier subpaths in document pixels, holes
|
|
930
|
+
* included (fill them even-odd), within `tolerance` px. Changes nothing. Throws without a selection.
|
|
931
|
+
*/
|
|
932
|
+
selectionToPath(options?: SelectionToPathOptions): {
|
|
933
|
+
subpaths: VectorSubpath[];
|
|
934
|
+
svg: string;
|
|
935
|
+
fillRule: 'evenodd';
|
|
936
|
+
bounds: CropBox | null;
|
|
937
|
+
anchors: number;
|
|
938
|
+
};
|
|
939
|
+
/**
|
|
940
|
+
* Make Selection: fills a path (`shape`, `subpaths` or `components`, document pixels) into a
|
|
941
|
+
* selection combined with the current one by `mode`, with `feather` px and `antiAlias`. One
|
|
942
|
+
* undo step. Returns whether anything is selected.
|
|
943
|
+
*/
|
|
944
|
+
pathToSelection(path: VectorMaskPathInput, options?: PathToSelectionOptions & {
|
|
945
|
+
mode?: SelectionMode;
|
|
946
|
+
}): boolean;
|
|
925
947
|
/** Replaces a vector mask's path (its properties are kept). One undo step. Returns the vector mask. */
|
|
926
948
|
setVectorMaskPath(id: string, path: VectorMaskPathInput): VectorMask;
|
|
927
949
|
/** Changes a vector mask's enabled, linked, inverted, density or feather (the path is kept). One undo step. */
|