@pixerate/editor 0.192.0 → 0.193.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.
Files changed (52) hide show
  1. package/dist/animation-editor/index.cjs +56 -56
  2. package/dist/animation-editor/index.js +2 -2
  3. package/dist/{chunk-ZQGZWFPU.cjs → chunk-3T5VCDIV.cjs} +97 -5
  4. package/dist/{chunk-RQ2EM5TY.js → chunk-5OC22IEO.js} +97 -5
  5. package/dist/{chunk-EGZM52EO.cjs → chunk-BRKVNXDZ.cjs} +354 -125
  6. package/dist/{chunk-XCDGM7TD.cjs → chunk-FR2Q2LVF.cjs} +35 -35
  7. package/dist/{chunk-LPIKXPBM.js → chunk-GHCXLQ47.js} +262 -33
  8. package/dist/{chunk-VRXXAXUT.js → chunk-MLC7HUHO.js} +1 -1
  9. package/dist/{chunk-2UR4OX3B.cjs → chunk-UYXL6ZWQ.cjs} +114 -97
  10. package/dist/{chunk-TXYXF32N.js → chunk-ZIDUPSP4.js} +35 -18
  11. package/dist/image-editor/controller.d.cts +16 -6
  12. package/dist/image-editor/controller.d.ts +16 -6
  13. package/dist/image-editor/index.cjs +867 -831
  14. package/dist/image-editor/index.js +103 -67
  15. package/dist/image-editor/layers/model.d.cts +7 -2
  16. package/dist/image-editor/layers/model.d.ts +7 -2
  17. package/dist/image-editor/layers/serialize.d.cts +2 -0
  18. package/dist/image-editor/layers/serialize.d.ts +2 -0
  19. package/dist/image-editor/layers/shape-type-ui.d.cts +8 -2
  20. package/dist/image-editor/layers/shape-type-ui.d.ts +8 -2
  21. package/dist/image-editor/layers/text.d.cts +6 -2
  22. package/dist/image-editor/layers/text.d.ts +6 -2
  23. package/dist/image-editor/psd/type.d.cts +2 -1
  24. package/dist/image-editor/psd/type.d.ts +2 -1
  25. package/dist/image-editor/tools.d.cts +1 -1
  26. package/dist/image-editor/tools.d.ts +1 -1
  27. package/dist/image-editor/type-tools.d.cts +2 -2
  28. package/dist/image-editor/type-tools.d.ts +2 -2
  29. package/dist/paint-editor/index.cjs +7 -7
  30. package/dist/paint-editor/index.js +2 -2
  31. package/dist/text/layout.d.cts +93 -12
  32. package/dist/text/layout.d.ts +93 -12
  33. package/dist/text/opentype.d.cts +13 -3
  34. package/dist/text/opentype.d.ts +13 -3
  35. package/dist/text/shapers.d.cts +12 -0
  36. package/dist/text/shapers.d.ts +12 -0
  37. package/dist/text/types.d.cts +36 -2
  38. package/dist/text/types.d.ts +36 -2
  39. package/dist/vector/controller.d.cts +8 -0
  40. package/dist/vector/controller.d.ts +8 -0
  41. package/dist/vector/index.cjs +1039 -967
  42. package/dist/vector/index.js +90 -18
  43. package/dist/vector/text.d.cts +5 -3
  44. package/dist/vector/text.d.ts +5 -3
  45. package/dist/vector/textPanel.d.cts +6 -0
  46. package/dist/vector/textPanel.d.ts +6 -0
  47. package/dist/vector/types.d.cts +9 -0
  48. package/dist/vector/types.d.ts +9 -0
  49. package/package.json +1 -1
  50. package/skills/pixerate-image-editor/SKILL.md +4 -3
  51. package/skills/pixerate-image-editor/references/shapes-and-type.md +17 -5
  52. package/skills/pixerate-vector/SKILL.md +9 -3
@@ -1,6 +1,6 @@
1
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; } var _class;
2
2
 
3
- var _chunkXCDGM7TDcjs = require('../chunk-XCDGM7TD.cjs');
3
+ var _chunkFR2Q2LVFcjs = require('../chunk-FR2Q2LVF.cjs');
4
4
 
5
5
 
6
6
 
@@ -31,7 +31,7 @@ var _chunkEBDZWIOPcjs = require('../chunk-EBDZWIOP.cjs');
31
31
 
32
32
 
33
33
 
34
- var _chunkEGZM52EOcjs = require('../chunk-EGZM52EO.cjs');
34
+ var _chunkBRKVNXDZcjs = require('../chunk-BRKVNXDZ.cjs');
35
35
  require('../chunk-YQ5C5BVK.cjs');
36
36
  require('../chunk-CVFAAZXE.cjs');
37
37
 
@@ -597,7 +597,7 @@ function smoothMotionTimes(points, start, duration, pacing = "even") {
597
597
  function motionTextLayout(nodes, id) {
598
598
  const group = _optionalChain([nodes, 'access', _5 => _5.get, 'call', _6 => _6(id), 'optionalAccess', _7 => _7.node]);
599
599
  if (!group || group.type !== "group") return null;
600
- const letters = _chunkEGZM52EOcjs.collectPathNodes.call(void 0, group).map((p) => ({ id: p.id, b: _optionalChain([nodes, 'access', _8 => _8.get, 'call', _9 => _9(p.id), 'optionalAccess', _10 => _10.bounds]) })).filter((l) => !!l.b && l.b.width + l.b.height > 0);
600
+ const letters = _chunkBRKVNXDZcjs.collectPathNodes.call(void 0, group).map((p) => ({ id: p.id, b: _optionalChain([nodes, 'access', _8 => _8.get, 'call', _9 => _9(p.id), 'optionalAccess', _10 => _10.bounds]) })).filter((l) => !!l.b && l.b.width + l.b.height > 0);
601
601
  if (!letters.length) return null;
602
602
  const lines = [];
603
603
  for (const l of [...letters].sort((a, c) => a.b.y + a.b.height / 2 - (c.b.y + c.b.height / 2))) {
@@ -682,21 +682,21 @@ function indexMotionNodes(nodes) {
682
682
  const out = /* @__PURE__ */ new Map();
683
683
  const walk = (list, parentWorld, ancestors) => {
684
684
  for (const node of list) {
685
- const local = _chunkEGZM52EOcjs.vectorNodeBounds.call(void 0, node);
686
- const bounds = _chunkEGZM52EOcjs.vectorNodeBounds.call(void 0, node, parentWorld);
685
+ const local = _chunkBRKVNXDZcjs.vectorNodeBounds.call(void 0, node);
686
+ const bounds = _chunkBRKVNXDZcjs.vectorNodeBounds.call(void 0, node, parentWorld);
687
687
  const center = local ? { x: local.x + local.width / 2, y: local.y + local.height / 2 } : { x: 0, y: 0 };
688
688
  if (!out.has(node.id)) out.set(node.id, { node, ancestors, parentWorld, center, bounds, box: local });
689
- if (node.type === "group") walk(node.children, _chunkEGZM52EOcjs.multiplyMatrices.call(void 0, _chunkEGZM52EOcjs.nodeMatrix.call(void 0, node), parentWorld), [...ancestors, node.id]);
689
+ if (node.type === "group") walk(node.children, _chunkBRKVNXDZcjs.multiplyMatrices.call(void 0, _chunkBRKVNXDZcjs.nodeMatrix.call(void 0, node), parentWorld), [...ancestors, node.id]);
690
690
  }
691
691
  };
692
- walk(nodes, _chunkEGZM52EOcjs.IDENTITY_MATRIX, []);
692
+ walk(nodes, _chunkBRKVNXDZcjs.IDENTITY_MATRIX, []);
693
693
  indexCache.set(nodes, out);
694
694
  return out;
695
695
  }
696
696
  var solid = (paint) => typeof paint === "string" && paint !== "none" ? paint : void 0;
697
697
  function firstPaint(node, key) {
698
698
  if (node.type === "path") return solid(node[key]);
699
- for (const p of _chunkEGZM52EOcjs.collectPathNodes.call(void 0, node)) {
699
+ for (const p of _chunkBRKVNXDZcjs.collectPathNodes.call(void 0, node)) {
700
700
  const s = solid(p[key]);
701
701
  if (s) return s;
702
702
  }
@@ -704,7 +704,7 @@ function firstPaint(node, key) {
704
704
  }
705
705
  function strokeReach(node) {
706
706
  let reach = 0;
707
- for (const p of node.type === "path" ? [node] : _chunkEGZM52EOcjs.collectPathNodes.call(void 0, node)) {
707
+ for (const p of node.type === "path" ? [node] : _chunkBRKVNXDZcjs.collectPathNodes.call(void 0, node)) {
708
708
  if (p.stroke == null || p.stroke === "none") continue;
709
709
  const width = _nullishCoalesce(p.strokeWidth, () => ( 1));
710
710
  reach = Math.max(reach, p.strokeAlign === "outside" ? width : p.strokeAlign === "inside" ? 0 : width / 2);
@@ -774,7 +774,7 @@ function motionRestValue(entry, property, artwork) {
774
774
  case "stroke":
775
775
  return _nullishCoalesce((node && firstPaint(node, property)), () => ( "transparent"));
776
776
  case "strokeWidth": {
777
- const path = _optionalChain([node, 'optionalAccess', _13 => _13.type]) === "path" ? node : node ? _chunkEGZM52EOcjs.collectPathNodes.call(void 0, node)[0] : void 0;
777
+ const path = _optionalChain([node, 'optionalAccess', _13 => _13.type]) === "path" ? node : node ? _chunkBRKVNXDZcjs.collectPathNodes.call(void 0, node)[0] : void 0;
778
778
  return _nullishCoalesce(_optionalChain([path, 'optionalAccess', _14 => _14.strokeWidth]), () => ( 1));
779
779
  }
780
780
  case "shape":
@@ -885,12 +885,12 @@ function resolveMotionCamera(camera, scene) {
885
885
  const r = camera;
886
886
  return { x: r.x, y: r.y, width: r.width, height: r.height };
887
887
  }
888
- function motionPathLength(node, parentWorld = _chunkEGZM52EOcjs.IDENTITY_MATRIX) {
888
+ function motionPathLength(node, parentWorld = _chunkBRKVNXDZcjs.IDENTITY_MATRIX) {
889
889
  let longest = 0;
890
- const paths = node.type === "path" ? [node] : _chunkEGZM52EOcjs.collectPathNodes.call(void 0, node);
890
+ const paths = node.type === "path" ? [node] : _chunkBRKVNXDZcjs.collectPathNodes.call(void 0, node);
891
891
  for (const p of paths) {
892
892
  try {
893
- longest = Math.max(longest, _chunkGF2RBSDMcjs.bezierPathLength.call(void 0, _chunkEGZM52EOcjs.vectorPathWorldBezier.call(void 0, p, parentWorld, { effects: false })));
893
+ longest = Math.max(longest, _chunkGF2RBSDMcjs.bezierPathLength.call(void 0, _chunkBRKVNXDZcjs.vectorPathWorldBezier.call(void 0, p, parentWorld, { effects: false })));
894
894
  } catch (e2) {
895
895
  }
896
896
  }
@@ -1143,12 +1143,12 @@ function compileMotionScene(scene) {
1143
1143
  const order2 = _nullishCoalesce(o.order, () => ( "together"));
1144
1144
  const pace = _nullishCoalesce(o.pace, () => ( "time"));
1145
1145
  if (order2 === "together" && pace === "time") return null;
1146
- const paths = entry.node.type === "path" ? [entry.node] : _chunkEGZM52EOcjs.collectPathNodes.call(void 0, entry.node);
1146
+ const paths = entry.node.type === "path" ? [entry.node] : _chunkBRKVNXDZcjs.collectPathNodes.call(void 0, entry.node);
1147
1147
  let list = paths.map((p) => {
1148
1148
  const at = nodes.get(p.id);
1149
1149
  let first = { x: 0, y: 0 };
1150
1150
  try {
1151
- const m = _chunkEGZM52EOcjs.vectorPathWorldBezier.call(void 0, p, _nullishCoalesce(_optionalChain([at, 'optionalAccess', _41 => _41.parentWorld]), () => ( _chunkEGZM52EOcjs.IDENTITY_MATRIX)), { effects: false })[0];
1151
+ const m = _chunkBRKVNXDZcjs.vectorPathWorldBezier.call(void 0, p, _nullishCoalesce(_optionalChain([at, 'optionalAccess', _41 => _41.parentWorld]), () => ( _chunkBRKVNXDZcjs.IDENTITY_MATRIX)), { effects: false })[0];
1152
1152
  if (m && m.type === "M") first = { x: m.x, y: m.y };
1153
1153
  } catch (e3) {
1154
1154
  }
@@ -1260,17 +1260,17 @@ function compileMotionScene(scene) {
1260
1260
  let dx = _nullishCoalesce(_optionalChain([command3, 'access', _44 => _44.by, 'optionalAccess', _45 => _45.x]), () => ( 0));
1261
1261
  let dy = _nullishCoalesce(_optionalChain([command3, 'access', _46 => _46.by, 'optionalAccess', _47 => _47.y]), () => ( 0));
1262
1262
  if (command3.to) {
1263
- const inv = _chunkEGZM52EOcjs.invertMatrix.call(void 0, entry.parentWorld);
1264
- const target = _chunkEGZM52EOcjs.applyMatrix.call(void 0, inv, command3.to);
1263
+ const inv = _chunkBRKVNXDZcjs.invertMatrix.call(void 0, entry.parentWorld);
1264
+ const target = _chunkBRKVNXDZcjs.applyMatrix.call(void 0, inv, command3.to);
1265
1265
  dx = target.x - (entry.center.x + num2("x"));
1266
1266
  dy = target.y - (entry.center.y + num2("y"));
1267
1267
  }
1268
1268
  if (_optionalChain([command3, 'access', _48 => _48.via, 'optionalAccess', _49 => _49.length])) {
1269
- const inv = _chunkEGZM52EOcjs.invertMatrix.call(void 0, entry.parentWorld);
1269
+ const inv = _chunkBRKVNXDZcjs.invertMatrix.call(void 0, entry.parentWorld);
1270
1270
  const x0 = num2("x");
1271
1271
  const y0 = num2("y");
1272
1272
  const add = command3.blend === "add";
1273
- const offsets = [{ x: 0, y: 0 }, ...command3.via.map((p) => _chunkEGZM52EOcjs.applyMatrix.call(void 0, inv, p)).map((p) => ({ x: p.x - entry.center.x - x0, y: p.y - entry.center.y - y0 })), { x: dx, y: dy }];
1273
+ const offsets = [{ x: 0, y: 0 }, ...command3.via.map((p) => _chunkBRKVNXDZcjs.applyMatrix.call(void 0, inv, p)).map((p) => ({ x: p.x - entry.center.x - x0, y: p.y - entry.center.y - y0 })), { x: dx, y: dy }];
1274
1274
  const times = _optionalChain([command3, 'access', _50 => _50.times, 'optionalAccess', _51 => _51.length]) === command3.via.length ? [start, ...command3.times.map((f) => start + f * (end - start)), end] : smoothMotionTimes(offsets, start, end - start, _nullishCoalesce(command3.pacing, () => ( "even")));
1275
1275
  for (const axis of ["x", "y"]) {
1276
1276
  const base = add ? 0 : axis === "x" ? x0 : y0;
@@ -1413,13 +1413,13 @@ function morphBetween(a, b) {
1413
1413
  let inner = morphCache.get(a);
1414
1414
  if (!inner) morphCache.set(a, inner = /* @__PURE__ */ new WeakMap());
1415
1415
  let morph = inner.get(b);
1416
- if (!morph) inner.set(b, morph = _chunkXCDGM7TDcjs.createVectorMorph.call(void 0, a, b, { id: a.id }));
1416
+ if (!morph) inner.set(b, morph = _chunkFR2Q2LVFcjs.createVectorMorph.call(void 0, a, b, { id: a.id }));
1417
1417
  return morph;
1418
1418
  }
1419
1419
  function shapeIn(entry, shape) {
1420
1420
  if (shape === entry) return entry.node;
1421
- const m = _chunkEGZM52EOcjs.multiplyMatrices.call(void 0, _chunkEGZM52EOcjs.multiplyMatrices.call(void 0, _chunkEGZM52EOcjs.nodeMatrix.call(void 0, shape.node), shape.parentWorld), _chunkEGZM52EOcjs.invertMatrix.call(void 0, entry.parentWorld));
1422
- return { ...shape.node, ..._chunkEGZM52EOcjs.isIdentityMatrix.call(void 0, m) ? { transform: void 0 } : { transform: m } };
1421
+ const m = _chunkBRKVNXDZcjs.multiplyMatrices.call(void 0, _chunkBRKVNXDZcjs.multiplyMatrices.call(void 0, _chunkBRKVNXDZcjs.nodeMatrix.call(void 0, shape.node), shape.parentWorld), _chunkBRKVNXDZcjs.invertMatrix.call(void 0, entry.parentWorld));
1422
+ return { ...shape.node, ..._chunkBRKVNXDZcjs.isIdentityMatrix.call(void 0, m) ? { transform: void 0 } : { transform: m } };
1423
1423
  }
1424
1424
  function shapeAt(entry, timeline, nodes, time) {
1425
1425
  const track = timeline.tracks.get(motionTrackKey(entry.node.id, "shape"));
@@ -1439,7 +1439,7 @@ function shapeAt(entry, timeline, nodes, time) {
1439
1439
  function motionFollowRoute(entry, path) {
1440
1440
  if (!path || path.node.type !== "path") return null;
1441
1441
  try {
1442
- return _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkEGZM52EOcjs.vectorPathWorldBezier.call(void 0, path.node, path.parentWorld, { effects: false }), _chunkEGZM52EOcjs.invertMatrix.call(void 0, entry.parentWorld));
1442
+ return _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkBRKVNXDZcjs.vectorPathWorldBezier.call(void 0, path.node, path.parentWorld, { effects: false }), _chunkBRKVNXDZcjs.invertMatrix.call(void 0, entry.parentWorld));
1443
1443
  } catch (e4) {
1444
1444
  return null;
1445
1445
  }
@@ -1473,9 +1473,9 @@ function motionNodeOffset(entry, timeline, time, nodes = indexMotionNodes([entry
1473
1473
  const scaleX = read("scaleX", 1);
1474
1474
  const scaleY = read("scaleY", 1);
1475
1475
  const c = entry.center;
1476
- let matrix = _chunkEGZM52EOcjs.multiplyMatrices.call(void 0, _chunkEGZM52EOcjs.multiplyMatrices.call(void 0, _chunkEGZM52EOcjs.scaleMatrix.call(void 0, scaleX, scaleY, c), _chunkEGZM52EOcjs.rotateMatrix.call(void 0, rotation, c)), _chunkEGZM52EOcjs.translateMatrix.call(void 0, dx, dy));
1476
+ let matrix = _chunkBRKVNXDZcjs.multiplyMatrices.call(void 0, _chunkBRKVNXDZcjs.multiplyMatrices.call(void 0, _chunkBRKVNXDZcjs.scaleMatrix.call(void 0, scaleX, scaleY, c), _chunkBRKVNXDZcjs.rotateMatrix.call(void 0, rotation, c)), _chunkBRKVNXDZcjs.translateMatrix.call(void 0, dx, dy));
1477
1477
  const along = follow ? followAt(entry, timeline, nodes, time) : null;
1478
- if (along) matrix = _chunkEGZM52EOcjs.multiplyMatrices.call(void 0, matrix, _chunkEGZM52EOcjs.multiplyMatrices.call(void 0, _chunkEGZM52EOcjs.multiplyMatrices.call(void 0, _chunkEGZM52EOcjs.translateMatrix.call(void 0, -c.x, -c.y), _chunkEGZM52EOcjs.rotateMatrix.call(void 0, along.angle)), _chunkEGZM52EOcjs.translateMatrix.call(void 0, along.x, along.y)));
1478
+ if (along) matrix = _chunkBRKVNXDZcjs.multiplyMatrices.call(void 0, matrix, _chunkBRKVNXDZcjs.multiplyMatrices.call(void 0, _chunkBRKVNXDZcjs.multiplyMatrices.call(void 0, _chunkBRKVNXDZcjs.translateMatrix.call(void 0, -c.x, -c.y), _chunkBRKVNXDZcjs.rotateMatrix.call(void 0, along.angle)), _chunkBRKVNXDZcjs.translateMatrix.call(void 0, along.x, along.y)));
1479
1479
  return { matrix, dx, dy, rotation, scaleX, scaleY, follow: along };
1480
1480
  }
1481
1481
  function motionNodeClips(id, timeline, time) {
@@ -1542,7 +1542,7 @@ function motionFrameAt(scene, time, options = {}) {
1542
1542
  const start = Math.min(1, Math.max(0, typeof drawStart === "number" ? drawStart : 0));
1543
1543
  const end = Math.min(1, Math.max(0, typeof drawEnd === "number" ? drawEnd : 1));
1544
1544
  if (start > 0 || end < 1) {
1545
- const trim = _chunkEGZM52EOcjs.createVectorEffect.call(void 0, "trim", MOTION_DRAW_EFFECT_ID, { start: tidy(start * 100), end: tidy(end * 100) });
1545
+ const trim = _chunkBRKVNXDZcjs.createVectorEffect.call(void 0, "trim", MOTION_DRAW_EFFECT_ID, { start: tidy(start * 100), end: tidy(end * 100) });
1546
1546
  p = { ...p, effects: [trim, ...(_nullishCoalesce(p.effects, () => ( []))).filter((e) => e.id !== MOTION_DRAW_EFFECT_ID)] };
1547
1547
  }
1548
1548
  }
@@ -1556,8 +1556,8 @@ function motionFrameAt(scene, time, options = {}) {
1556
1556
  if (o >= 1) delete out.opacity;
1557
1557
  }
1558
1558
  const offset = options.offsets === false ? null : motionNodeOffset(entry, timeline, time, nodes);
1559
- if (offset && !_chunkEGZM52EOcjs.isIdentityMatrix.call(void 0, offset.matrix)) {
1560
- const m = _chunkEGZM52EOcjs.multiplyMatrices.call(void 0, _chunkEGZM52EOcjs.nodeMatrix.call(void 0, out), offset.matrix).map(tidy);
1559
+ if (offset && !_chunkBRKVNXDZcjs.isIdentityMatrix.call(void 0, offset.matrix)) {
1560
+ const m = _chunkBRKVNXDZcjs.multiplyMatrices.call(void 0, _chunkBRKVNXDZcjs.nodeMatrix.call(void 0, out), offset.matrix).map(tidy);
1561
1561
  out = { ...out, transform: m };
1562
1562
  }
1563
1563
  return out;
@@ -1577,7 +1577,7 @@ function motionFrameToSvg(scene, time, options = {}) {
1577
1577
  const wrap = { ...options.wrap };
1578
1578
  for (const [id, clips] of Object.entries(frame.clips))
1579
1579
  wrap[id] = [..._nullishCoalesce(wrap[id], () => ( [])), ...clips.map((clip, i) => ({ clip: { id: `${prefix}reveal-${id}-${i}`, shape: clip.shape, attrs: motionClipAttrs(clip) } }))];
1580
- return withViewBox(_chunkEGZM52EOcjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap }), frame.camera);
1580
+ return withViewBox(_chunkBRKVNXDZcjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap }), frame.camera);
1581
1581
  }
1582
1582
  function withViewBox(svg, box) {
1583
1583
  const f = (n) => String(Math.round(n * 1e3) / 1e3);
@@ -1760,8 +1760,8 @@ function visibleAt(timeline, id, time, node) {
1760
1760
  if (Array.isArray(rect) && (rect[2] <= 1e-4 || rect[3] <= 1e-4)) return false;
1761
1761
  const circle = clip("clipCircle");
1762
1762
  if (Array.isArray(circle) && circle[2] <= 1e-4) return false;
1763
- const hasFill = node.type === "path" ? !!node.fill && node.fill !== "none" : _chunkEGZM52EOcjs.collectPathNodes.call(void 0, node).some((p) => p.fill && p.fill !== "none");
1764
- const drawn = num2("drawEnd", 1) > 0.01 && (node.type === "path" || _chunkEGZM52EOcjs.collectPathNodes.call(void 0, node).length === 0 || _chunkEGZM52EOcjs.collectPathNodes.call(void 0, node).some((p) => {
1763
+ const hasFill = node.type === "path" ? !!node.fill && node.fill !== "none" : _chunkBRKVNXDZcjs.collectPathNodes.call(void 0, node).some((p) => p.fill && p.fill !== "none");
1764
+ const drawn = num2("drawEnd", 1) > 0.01 && (node.type === "path" || _chunkBRKVNXDZcjs.collectPathNodes.call(void 0, node).length === 0 || _chunkBRKVNXDZcjs.collectPathNodes.call(void 0, node).some((p) => {
1765
1765
  const v = trackValue(timeline.tracks.get(motionTrackKey(p.id, "drawEnd")), time);
1766
1766
  return typeof v !== "number" || v > 0.01;
1767
1767
  }));
@@ -1847,7 +1847,7 @@ function checkMotionScene(scene) {
1847
1847
  }
1848
1848
  for (const id of targets) {
1849
1849
  const node = nodes.get(id).node;
1850
- const paths = node.type === "path" ? [node] : _chunkEGZM52EOcjs.collectPathNodes.call(void 0, node);
1850
+ const paths = node.type === "path" ? [node] : _chunkBRKVNXDZcjs.collectPathNodes.call(void 0, node);
1851
1851
  if (paths.some((p) => p[key] !== void 0 && p[key] !== null && typeof p[key] !== "string"))
1852
1852
  issues.push(_chunkEBDZWIOPcjs.motionIssue.call(void 0, "paint-not-color", `"${id}" has a gradient ${key}; it switches to ${color} at the end instead of blending.`, { ...where, ids: [id] }));
1853
1853
  }
@@ -1860,7 +1860,7 @@ function checkMotionScene(scene) {
1860
1860
  else
1861
1861
  for (const id of targets) {
1862
1862
  const node = nodes.get(id).node;
1863
- const paths = node.type === "path" ? [node] : _chunkEGZM52EOcjs.collectPathNodes.call(void 0, node);
1863
+ const paths = node.type === "path" ? [node] : _chunkBRKVNXDZcjs.collectPathNodes.call(void 0, node);
1864
1864
  if (paths.some((p) => typeof p[key] !== "string"))
1865
1865
  issues.push(_chunkEBDZWIOPcjs.motionIssue.call(void 0, "paint-not-color", `"${id}" has a gradient or no ${key}, so a colour pulse cannot tint it; give it a solid ${key} or pulse the ${key === "fill" ? "stroke" : "fill"}.`, { ...where, ids: [id] }));
1866
1866
  }
@@ -2305,7 +2305,7 @@ function motionNodePose(scene, id, time) {
2305
2305
  if (!entry) throw new Error(`There is no element ${_chunkEBDZWIOPcjs.namedWithSuggestion.call(void 0, id, [...indexMotionNodes(scene.artwork.nodes).keys()])} in the artwork.`);
2306
2306
  const timeline = compileMotionScene(scene);
2307
2307
  const drawn = indexMotionNodes(motionFrameAt(scene, time).document.nodes).get(id);
2308
- const centre = _chunkEGZM52EOcjs.applyMatrix.call(void 0, entry.parentWorld, { x: entry.center.x + motionPropertyValue(timeline, id, "x", time), y: entry.center.y + motionPropertyValue(timeline, id, "y", time) });
2308
+ const centre = _chunkBRKVNXDZcjs.applyMatrix.call(void 0, entry.parentWorld, { x: entry.center.x + motionPropertyValue(timeline, id, "x", time), y: entry.center.y + motionPropertyValue(timeline, id, "y", time) });
2309
2309
  const paint = (property) => _nullishCoalesce(trackValue(timeline.tracks.get(motionTrackKey(id, property)), time), () => ( motionRestValue(entry, property, scene.artwork)));
2310
2310
  const fill = paint("fill");
2311
2311
  const stroke = paint("stroke");
@@ -2652,7 +2652,7 @@ function toFlairSvgMotion(scene, options = {}) {
2652
2652
  raw: (t) => transformAt(t, true)
2653
2653
  });
2654
2654
  }
2655
- const paths = node.type === "path" ? [node] : _chunkEGZM52EOcjs.collectPathNodes.call(void 0, node);
2655
+ const paths = node.type === "path" ? [node] : _chunkBRKVNXDZcjs.collectPathNodes.call(void 0, node);
2656
2656
  for (const path of paths) {
2657
2657
  if (pathsSeen.has(path.id)) continue;
2658
2658
  pathsSeen.add(path.id);
@@ -2674,7 +2674,7 @@ function toFlairSvgMotion(scene, options = {}) {
2674
2674
  if (shapeSegments.length) {
2675
2675
  if (node.type !== "path") notes.push(`"${id}" is a group: its morph or effect animation is not exported (Flair tweens one path's "d").`);
2676
2676
  else {
2677
- const inverse = _chunkEGZM52EOcjs.invertMatrix.call(void 0, _chunkEGZM52EOcjs.nodeMatrix.call(void 0, node));
2677
+ const inverse = _chunkBRKVNXDZcjs.invertMatrix.call(void 0, _chunkBRKVNXDZcjs.nodeMatrix.call(void 0, node));
2678
2678
  channels.push({
2679
2679
  id,
2680
2680
  kind: "attr",
@@ -2683,9 +2683,9 @@ function toFlairSvgMotion(scene, options = {}) {
2683
2683
  exact: () => false,
2684
2684
  value: (t) => {
2685
2685
  const frame = motionFrameAt(scene, t, { draw: false, offsets: false });
2686
- const now = _chunkEGZM52EOcjs.expandVectorAppearance.call(void 0, _optionalChain([indexMotionNodes, 'call', _114 => _114(frame.document.nodes), 'access', _115 => _115.get, 'call', _116 => _116(id), 'optionalAccess', _117 => _117.node]));
2686
+ const now = _chunkBRKVNXDZcjs.expandVectorAppearance.call(void 0, _optionalChain([indexMotionNodes, 'call', _114 => _114(frame.document.nodes), 'access', _115 => _115.get, 'call', _116 => _116(id), 'optionalAccess', _117 => _117.node]));
2687
2687
  if (!now || now.type !== "path") return "";
2688
- const bezier = _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkEGZM52EOcjs.vectorPathWorldBezier.call(void 0, now, _chunkEGZM52EOcjs.IDENTITY_MATRIX, { effects: false }), inverse);
2688
+ const bezier = _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkBRKVNXDZcjs.vectorPathWorldBezier.call(void 0, now, _chunkBRKVNXDZcjs.IDENTITY_MATRIX, { effects: false }), inverse);
2689
2689
  return _chunkGF2RBSDMcjs.bezierPathToSvg.call(void 0, bezier, { precision: Math.min(precision, 2) });
2690
2690
  }
2691
2691
  });
@@ -2792,7 +2792,7 @@ function toFlairSvgMotion(scene, options = {}) {
2792
2792
  }
2793
2793
  if (scene.motionBlur) notes.push("Motion blur is drawn on the stage only; Flair plays the scene sharp.");
2794
2794
  if (trigger && (_nullishCoalesce(scene.loop, () => ( "none"))) !== "none") notes.push(`The scene plays on ${trigger}, so its loop does not apply in Flair.`);
2795
- let svg = _chunkEGZM52EOcjs.vectorDocumentToSvg.call(void 0, { ...scene.artwork, nodes: _chunkEGZM52EOcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) }, { pretty: false, precision, wrap });
2795
+ let svg = _chunkBRKVNXDZcjs.vectorDocumentToSvg.call(void 0, { ...scene.artwork, nodes: _chunkBRKVNXDZcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) }, { pretty: false, precision, wrap });
2796
2796
  if (routes.length) svg = svg.replace(/^(<svg[^>]*>)/, `$1<defs>${routes.join("")}</defs>`);
2797
2797
  let motion = { svg, animate };
2798
2798
  if (_optionalChain([scene, 'access', _120 => _120.controls, 'optionalAccess', _121 => _121.length])) {
@@ -2876,14 +2876,14 @@ function easingOf(ease, fallback) {
2876
2876
  return fallback;
2877
2877
  }
2878
2878
  function poseOf(value, entry) {
2879
- const t = _chunkEGZM52EOcjs.parseSvgTransform.call(void 0, String(value));
2880
- const o = _chunkEGZM52EOcjs.multiplyMatrices.call(void 0, _nullishCoalesce(_chunkEGZM52EOcjs.invertMatrix.call(void 0, _chunkEGZM52EOcjs.nodeMatrix.call(void 0, entry.node)), () => ( [1, 0, 0, 1, 0, 0])), t);
2879
+ const t = _chunkBRKVNXDZcjs.parseSvgTransform.call(void 0, String(value));
2880
+ const o = _chunkBRKVNXDZcjs.multiplyMatrices.call(void 0, _nullishCoalesce(_chunkBRKVNXDZcjs.invertMatrix.call(void 0, _chunkBRKVNXDZcjs.nodeMatrix.call(void 0, entry.node)), () => ( [1, 0, 0, 1, 0, 0])), t);
2881
2881
  const sx = Math.hypot(o[0], o[1]);
2882
2882
  if (!(sx > 1e-9)) return null;
2883
2883
  const sy = (o[0] * o[3] - o[1] * o[2]) / sx;
2884
2884
  if (Math.abs(o[2] + o[1] / sx * sy) > 1e-6 || Math.abs(o[3] - o[0] / sx * sy) > 1e-6) return null;
2885
2885
  const c = entry.center;
2886
- const moved = _chunkEGZM52EOcjs.applyMatrix.call(void 0, o, c);
2886
+ const moved = _chunkBRKVNXDZcjs.applyMatrix.call(void 0, o, c);
2887
2887
  return { dx: moved.x - c.x, dy: moved.y - c.y, rotation: Math.atan2(o[1], o[0]) * 180 / Math.PI, sx, sy };
2888
2888
  }
2889
2889
  var near = (a, b, eps = 1e-6) => Math.abs(a - b) < eps;
@@ -2968,7 +2968,7 @@ function fromFlairSvgMotion(input, options = {}) {
2968
2968
  const notes = [];
2969
2969
  if (!input || typeof input.svg !== "string") throw new Error('Give a Flair SvgMotion: { svg: "<svg \u2026>", animate: [ \u2026 ] }.');
2970
2970
  const { motion, controls } = resolvePlaceholders(input, notes);
2971
- const artwork = _chunkEGZM52EOcjs.parseVectorSvg.call(void 0, motion.svg);
2971
+ const artwork = _chunkBRKVNXDZcjs.parseVectorSvg.call(void 0, motion.svg);
2972
2972
  const nodes = indexMotionNodes(artwork.nodes);
2973
2973
  const byStep = /* @__PURE__ */ new Map();
2974
2974
  for (const anim of _nullishCoalesce(motion.animate, () => ( []))) {
@@ -3215,9 +3215,9 @@ function toLottie(scene, options = {}) {
3215
3215
  const items = [];
3216
3216
  const shapeSegments = [...timeline.tracks.entries()].filter(([k]) => k.startsWith(`${path.id}\0`) && (k.endsWith("\0shape") || k.includes("\0effect:"))).flatMap(([, v]) => v);
3217
3217
  const geometryAt = (t) => {
3218
- if (!shapeSegments.length) return _chunkEGZM52EOcjs.vectorPathWorldBezier.call(void 0, path);
3218
+ if (!shapeSegments.length) return _chunkBRKVNXDZcjs.vectorPathWorldBezier.call(void 0, path);
3219
3219
  const now = _optionalChain([indexMotionNodes, 'call', _130 => _130(motionFrameAt(scene, t, { draw: false, offsets: false }).document.nodes), 'access', _131 => _131.get, 'call', _132 => _132(path.id), 'optionalAccess', _133 => _133.node]);
3220
- return now && now.type === "path" ? _chunkEGZM52EOcjs.vectorPathWorldBezier.call(void 0, _chunkEGZM52EOcjs.expandVectorAppearances.call(void 0, [now])[0]) : _chunkEGZM52EOcjs.vectorPathWorldBezier.call(void 0, path);
3220
+ return now && now.type === "path" ? _chunkBRKVNXDZcjs.vectorPathWorldBezier.call(void 0, _chunkBRKVNXDZcjs.expandVectorAppearances.call(void 0, [now])[0]) : _chunkBRKVNXDZcjs.vectorPathWorldBezier.call(void 0, path);
3221
3221
  };
3222
3222
  const rest = lottieContours(_chunkGF2RBSDMcjs.toBezierPath.call(void 0, geometryAt(0)), round3);
3223
3223
  rest.forEach((contour, n) => {
@@ -3290,13 +3290,13 @@ function toLottie(scene, options = {}) {
3290
3290
  const innerTr = STATIC_TR();
3291
3291
  if (node.type === "path") inner = [...pathShapes(node)];
3292
3292
  else if (node.type === "text" || node.type === "instance") {
3293
- const drawn = _chunkEGZM52EOcjs.expandVectorAppearance.call(void 0, node);
3293
+ const drawn = _chunkBRKVNXDZcjs.expandVectorAppearance.call(void 0, node);
3294
3294
  inner = drawn.type === "path" ? [...pathShapes(drawn)] : drawn.children.filter((c) => c.type === "path").reverse().flatMap((c) => [...pathShapes(c)]);
3295
- notes.push(`"${node.id}": text is exported as its outlines${_chunkEGZM52EOcjs.vectorTextHasOutlines.call(void 0, ) ? "" : " (glyph boxes: set an outline text shaper for real glyphs)"}.`);
3295
+ notes.push(`"${node.id}": text is exported as its outlines${_chunkBRKVNXDZcjs.vectorTextHasOutlines.call(void 0, ) ? "" : " (glyph boxes: set an outline text shaper for real glyphs)"}.`);
3296
3296
  } else {
3297
3297
  inner = shown(node.children).reverse().map(nodeGroup);
3298
- const m = _chunkEGZM52EOcjs.nodeMatrix.call(void 0, node);
3299
- if (m !== _chunkEGZM52EOcjs.IDENTITY_MATRIX) {
3298
+ const m = _chunkBRKVNXDZcjs.nodeMatrix.call(void 0, node);
3299
+ if (m !== _chunkBRKVNXDZcjs.IDENTITY_MATRIX) {
3300
3300
  const parts = staticParts(m);
3301
3301
  if (!parts) notes.push(`"${node.id}": its transform skews, which is not exported; it is drawn without the skew.`);
3302
3302
  else {
@@ -3309,7 +3309,7 @@ function toLottie(scene, options = {}) {
3309
3309
  const body = { ty: "gr", nm: `${node.id} (own)`, it: [...inner, innerTr] };
3310
3310
  return { ty: "gr", nm: _nullishCoalesce(node.name, () => ( node.id)), it: [body, poseTransform(entry)] };
3311
3311
  };
3312
- const artwork = { ...scene.artwork, nodes: _chunkEGZM52EOcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) };
3312
+ const artwork = { ...scene.artwork, nodes: _chunkBRKVNXDZcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) };
3313
3313
  const content = shown(artwork.nodes).reverse().map(nodeGroup);
3314
3314
  if (artwork.background && rgba(artwork.background))
3315
3315
  content.push({ ty: "gr", nm: "Background", it: [{ ty: "rc", nm: "Background", p: { a: 0, k: [artwork.width / 2, artwork.height / 2] }, s: { a: 0, k: [artwork.width, artwork.height] }, r: { a: 0, k: 0 } }, { ty: "fl", c: { a: 0, k: rgba(artwork.background).map(round3) }, o: { a: 0, k: 100 }, r: 1 }, STATIC_TR()] });
@@ -3408,11 +3408,11 @@ function preset(prst, w, h) {
3408
3408
  const poly = (pts) => [{ closed: true, anchors: pts.map(([x, y]) => ({ x, y })) }];
3409
3409
  switch (prst) {
3410
3410
  case "rect":
3411
- return [_chunkEGZM52EOcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
3411
+ return [_chunkBRKVNXDZcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
3412
3412
  case "roundRect":
3413
- return [_chunkEGZM52EOcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h }, Math.min(w, h) * 0.16667)];
3413
+ return [_chunkBRKVNXDZcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h }, Math.min(w, h) * 0.16667)];
3414
3414
  case "ellipse":
3415
- return [_chunkEGZM52EOcjs.ellipseSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
3415
+ return [_chunkBRKVNXDZcjs.ellipseSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
3416
3416
  case "triangle":
3417
3417
  return poly([[w / 2, 0], [w, h], [0, h]]);
3418
3418
  case "rtTriangle":
@@ -3520,7 +3520,7 @@ function shapes(ctx, tree, map) {
3520
3520
  let subpaths = cust ? custom(cust, w, h) : prst ? preset(prst, w, h) : null;
3521
3521
  if (!subpaths) {
3522
3522
  if (prst) ctx.notes.push(`"${name}" is a ${prst}, drawn as its bounding rectangle.`);
3523
- subpaths = [_chunkEGZM52EOcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
3523
+ subpaths = [_chunkBRKVNXDZcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
3524
3524
  }
3525
3525
  const style = kid(el, "style");
3526
3526
  const fill = kid(spPr, "noFill") ? null : _nullishCoalesce(colour(ctx, kid(spPr, "solidFill")), () => ( (el.localName === "cxnSp" ? null : colour(ctx, kid(style, "fillRef")))));
@@ -3758,7 +3758,7 @@ function nextMotionEffectInstance(scene) {
3758
3758
  walk(scene.artwork.nodes);
3759
3759
  for (let i = 1; ; i++) if (!used.has(`fx${i}`)) return `fx${i}`;
3760
3760
  }
3761
- var motionArtworkSvg = (artwork) => _chunkEGZM52EOcjs.vectorDocumentToSvg.call(void 0, artwork);
3761
+ var motionArtworkSvg = (artwork) => _chunkBRKVNXDZcjs.vectorDocumentToSvg.call(void 0, artwork);
3762
3762
  var tag = (commands, source) => commands.map((c) => c.type === "wait" ? c : { ...c, source });
3763
3763
  function motionCommandsFromEffect(artwork, motion, source) {
3764
3764
  const imported = fromFlairSvgMotion({ svg: motionArtworkSvg(artwork), animate: [..._nullishCoalesce(motion.animate, () => ( []))] });
@@ -5085,7 +5085,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
5085
5085
  handler: ({ svg }) => {
5086
5086
  let artwork;
5087
5087
  try {
5088
- artwork = _chunkEGZM52EOcjs.parseVectorSvg.call(void 0, svg);
5088
+ artwork = _chunkBRKVNXDZcjs.parseVectorSvg.call(void 0, svg);
5089
5089
  } catch (error) {
5090
5090
  throw new Error(`The SVG could not be read: ${error.message}. Nothing was changed.`);
5091
5091
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createVectorMorph
3
- } from "../chunk-VRXXAXUT.js";
3
+ } from "../chunk-MLC7HUHO.js";
4
4
  import {
5
5
  MOTION_ISSUE_CODES,
6
6
  motionIssue,
@@ -31,7 +31,7 @@ import {
31
31
  vectorNodeBounds,
32
32
  vectorPathWorldBezier,
33
33
  vectorTextHasOutlines
34
- } from "../chunk-LPIKXPBM.js";
34
+ } from "../chunk-GHCXLQ47.js";
35
35
  import "../chunk-YXKLVD56.js";
36
36
  import "../chunk-M6DNZNVY.js";
37
37
  import {
@@ -1061,6 +1061,59 @@ function gposKerning(view, t) {
1061
1061
  return 0;
1062
1062
  };
1063
1063
  }
1064
+ function coverageGlyphs(view, at) {
1065
+ const format = view.getUint16(at);
1066
+ const n = view.getUint16(at + 2);
1067
+ const out = [];
1068
+ if (format === 1) for (let i = 0; i < n; i++) out.push(view.getUint16(at + 4 + i * 2));
1069
+ else if (format === 2)
1070
+ for (let i = 0; i < n; i++) {
1071
+ const r = at + 4 + i * 6;
1072
+ for (let g = view.getUint16(r); g <= view.getUint16(r + 2); g++) out.push(g);
1073
+ }
1074
+ return out;
1075
+ }
1076
+ function gsubVertical(view, t) {
1077
+ const out = /* @__PURE__ */ new Map();
1078
+ if (!t || t.length < 10) return out;
1079
+ const base = t.offset;
1080
+ const features = base + view.getUint16(base + 6);
1081
+ const lookups = base + view.getUint16(base + 8);
1082
+ const ids = /* @__PURE__ */ new Set();
1083
+ const nf = view.getUint16(features);
1084
+ for (let i = 0; i < nf; i++) {
1085
+ const rec = features + 2 + i * 6;
1086
+ let tag = "";
1087
+ for (let k = 0; k < 4; k++) tag += String.fromCharCode(view.getUint8(rec + k));
1088
+ if (tag !== "vert") continue;
1089
+ const f = features + view.getUint16(rec + 4);
1090
+ const n = view.getUint16(f + 2);
1091
+ for (let k = 0; k < n; k++) ids.add(view.getUint16(f + 4 + k * 2));
1092
+ }
1093
+ const nl = view.getUint16(lookups);
1094
+ for (const id of [...ids].sort((a, b) => a - b)) {
1095
+ if (id >= nl) continue;
1096
+ const l = lookups + view.getUint16(lookups + 2 + id * 2);
1097
+ const n = view.getUint16(l + 4);
1098
+ for (let k = 0; k < n; k++) {
1099
+ let type = view.getUint16(l);
1100
+ let st = l + view.getUint16(l + 6 + k * 2);
1101
+ if (type === 7) {
1102
+ type = view.getUint16(st + 2);
1103
+ st = st + view.getUint32(st + 4);
1104
+ }
1105
+ if (type !== 1) continue;
1106
+ const format = view.getUint16(st);
1107
+ const glyphs = coverageGlyphs(view, st + view.getUint16(st + 2));
1108
+ glyphs.forEach((g, i) => {
1109
+ if (out.has(g)) return;
1110
+ if (format === 1) out.set(g, (g + view.getInt16(st + 4) + 65536) % 65536);
1111
+ else if (format === 2 && i < view.getUint16(st + 4)) out.set(g, view.getUint16(st + 6 + i * 2));
1112
+ });
1113
+ }
1114
+ }
1115
+ return out;
1116
+ }
1064
1117
  var toView = (data) => data instanceof ArrayBuffer ? new DataView(data) : new DataView(data.buffer, data.byteOffset, data.byteLength);
1065
1118
  function parseOpenTypeFont(data, options = {}) {
1066
1119
  const view = toView(data);
@@ -1125,6 +1178,12 @@ function parseOpenTypeFont(data, options = {}) {
1125
1178
  if (i >= 0 && hmtx.offset + i * 4 + 2 <= hmtx.offset + hmtx.length) return view.getUint16(hmtx.offset + i * 4);
1126
1179
  return _nullishCoalesce(_optionalChain([cffWidth, 'optionalCall', _20 => _20(g)]), () => ( 0));
1127
1180
  };
1181
+ const vhea = tables.get("vhea");
1182
+ const vmtx = tables.get("vmtx");
1183
+ const numVMetrics = vhea && vhea.length >= 36 ? view.getUint16(vhea.offset + 34) : 0;
1184
+ const hasVerticalMetrics = Boolean(vmtx && numVMetrics > 0);
1185
+ const vorg = tables.get("VORG");
1186
+ const vertSub = gsubVertical(view, tables.get("GSUB"));
1128
1187
  const kernPairs = readKern(view, tables.get("kern"));
1129
1188
  const gpos = gposKerning(view, tables.get("GPOS"));
1130
1189
  const kerning = (a, b) => (gpos ? gpos(a, b) : 0) || kernPairs.get(a * 65536 + b) || 0;
@@ -1139,17 +1198,43 @@ function parseOpenTypeFont(data, options = {}) {
1139
1198
  }
1140
1199
  return p;
1141
1200
  };
1142
- const glyphs = (text) => {
1201
+ const verticalGlyph = (g) => _nullishCoalesce(vertSub.get(g), () => ( g));
1202
+ const vertOrigin = (g) => {
1203
+ if (vorg && vorg.length >= 8) {
1204
+ const n = view.getUint16(vorg.offset + 6);
1205
+ let lo = 0;
1206
+ let hi = n - 1;
1207
+ while (lo <= hi) {
1208
+ const mid = lo + hi >> 1;
1209
+ const at2 = vorg.offset + 8 + mid * 4;
1210
+ const v = view.getUint16(at2);
1211
+ if (v === g) return view.getInt16(at2 + 2);
1212
+ if (v < g) lo = mid + 1;
1213
+ else hi = mid - 1;
1214
+ }
1215
+ return view.getInt16(vorg.offset + 4);
1216
+ }
1217
+ if (!hasVerticalMetrics) return ascender;
1218
+ const tsb = g < numVMetrics ? view.getInt16(vmtx.offset + g * 4 + 2) : view.getInt16(vmtx.offset + numVMetrics * 4 + (g - numVMetrics) * 2);
1219
+ let top = -Infinity;
1220
+ for (const c of glyphPath(g)) for (const v of [c.y, c.y1, c.y2]) if (v !== void 0 && v > top) top = v;
1221
+ return Number.isFinite(top) ? top + tsb : ascender;
1222
+ };
1223
+ const verticalAdvance = (g) => {
1224
+ if (!hasVerticalMetrics || g < 0 || g >= numGlyphs) return ascender - descender;
1225
+ return view.getUint16(vmtx.offset + Math.min(g, numVMetrics - 1) * 4);
1226
+ };
1227
+ const glyphs = (text, vertical = false) => {
1143
1228
  const out = [];
1144
1229
  for (const ch of text) {
1145
1230
  const cp = ch.codePointAt(0);
1146
1231
  if (cp >= 55296 && cp <= 57343 || cp === 10 || cp === 13) continue;
1147
- out.push(glyphIndex(cp));
1232
+ out.push(vertical ? verticalGlyph(glyphIndex(cp)) : glyphIndex(cp));
1148
1233
  }
1149
1234
  return out;
1150
1235
  };
1151
- const layout = (text, kern) => {
1152
- const gs = glyphs(text);
1236
+ const layout = (text, kern, vertical = false) => {
1237
+ const gs = glyphs(text, vertical);
1153
1238
  const xs = [];
1154
1239
  let x = 0;
1155
1240
  for (let i = 0; i < gs.length; i++) {
@@ -1176,12 +1261,19 @@ function parseOpenTypeFont(data, options = {}) {
1176
1261
  advance,
1177
1262
  kerning,
1178
1263
  glyphPath,
1264
+ hasVerticalMetrics,
1265
+ verticalGlyph,
1266
+ getVerticalMetrics(char) {
1267
+ const g = glyphIndex(_nullishCoalesce(char.codePointAt(0), () => ( 0)));
1268
+ const v = verticalGlyph(g);
1269
+ return { advance: verticalAdvance(v), originY: vertOrigin(v), alternate: v !== g };
1270
+ },
1179
1271
  getAdvanceWidth(text, fontSize, opts) {
1180
1272
  return layout(text, _optionalChain([opts, 'optionalAccess', _21 => _21.kerning]) !== false).width * fontSize / unitsPerEm;
1181
1273
  },
1182
1274
  getPath(text, x, y, fontSize, opts) {
1183
1275
  const k = fontSize / unitsPerEm;
1184
- const { gs, xs } = layout(text, _optionalChain([opts, 'optionalAccess', _22 => _22.kerning]) !== false);
1276
+ const { gs, xs } = layout(text, _optionalChain([opts, 'optionalAccess', _22 => _22.kerning]) !== false, Boolean(_optionalChain([opts, 'optionalAccess', _23 => _23.vertical])));
1185
1277
  const commands = [];
1186
1278
  gs.forEach((g, i) => {
1187
1279
  const ox = x + xs[i] * k;