@pixerate/editor 0.192.0 → 0.194.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 (56) 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 +945 -831
  14. package/dist/image-editor/index.d.cts +1 -0
  15. package/dist/image-editor/index.d.ts +1 -0
  16. package/dist/image-editor/index.js +181 -67
  17. package/dist/image-editor/layers/model.d.cts +7 -2
  18. package/dist/image-editor/layers/model.d.ts +7 -2
  19. package/dist/image-editor/layers/serialize.d.cts +2 -0
  20. package/dist/image-editor/layers/serialize.d.ts +2 -0
  21. package/dist/image-editor/layers/shape-type-ui.d.cts +8 -2
  22. package/dist/image-editor/layers/shape-type-ui.d.ts +8 -2
  23. package/dist/image-editor/layers/text.d.cts +6 -2
  24. package/dist/image-editor/layers/text.d.ts +6 -2
  25. package/dist/image-editor/psd/type.d.cts +2 -1
  26. package/dist/image-editor/psd/type.d.ts +2 -1
  27. package/dist/image-editor/tool-groups.d.cts +35 -0
  28. package/dist/image-editor/tool-groups.d.ts +35 -0
  29. package/dist/image-editor/tools.d.cts +1 -1
  30. package/dist/image-editor/tools.d.ts +1 -1
  31. package/dist/image-editor/type-tools.d.cts +2 -2
  32. package/dist/image-editor/type-tools.d.ts +2 -2
  33. package/dist/paint-editor/index.cjs +7 -7
  34. package/dist/paint-editor/index.js +2 -2
  35. package/dist/text/layout.d.cts +93 -12
  36. package/dist/text/layout.d.ts +93 -12
  37. package/dist/text/opentype.d.cts +13 -3
  38. package/dist/text/opentype.d.ts +13 -3
  39. package/dist/text/shapers.d.cts +12 -0
  40. package/dist/text/shapers.d.ts +12 -0
  41. package/dist/text/types.d.cts +36 -2
  42. package/dist/text/types.d.ts +36 -2
  43. package/dist/vector/controller.d.cts +8 -0
  44. package/dist/vector/controller.d.ts +8 -0
  45. package/dist/vector/index.cjs +1039 -967
  46. package/dist/vector/index.js +90 -18
  47. package/dist/vector/text.d.cts +5 -3
  48. package/dist/vector/text.d.ts +5 -3
  49. package/dist/vector/textPanel.d.cts +6 -0
  50. package/dist/vector/textPanel.d.ts +6 -0
  51. package/dist/vector/types.d.cts +9 -0
  52. package/dist/vector/types.d.ts +9 -0
  53. package/package.json +1 -1
  54. package/skills/pixerate-image-editor/SKILL.md +4 -3
  55. package/skills/pixerate-image-editor/references/shapes-and-type.md +17 -5
  56. package/skills/pixerate-vector/SKILL.md +9 -3
@@ -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 cffWidth?.(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) => 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(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, opts?.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, opts?.kerning !== false);
1276
+ const { gs, xs } = layout(text, opts?.kerning !== false, Boolean(opts?.vertical));
1185
1277
  const commands = [];
1186
1278
  gs.forEach((g, i) => {
1187
1279
  const ox = x + xs[i] * k;