@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
@@ -2,7 +2,7 @@ import {
2
2
  loadOpenTypeFont,
3
3
  parseOpenTypeFont,
4
4
  traceField
5
- } from "../chunk-RQ2EM5TY.js";
5
+ } from "../chunk-5OC22IEO.js";
6
6
  import {
7
7
  ADJUSTMENT_KEYS,
8
8
  ADJUSTMENT_KINDS,
@@ -46,6 +46,7 @@ import {
46
46
  SMART_RENDER_MARGIN,
47
47
  SUPPORTED_ADJUSTMENT_KEYS,
48
48
  TEXT_ALIGNS,
49
+ TEXT_ORIENTATIONS,
49
50
  TEXT_RENDER_MARGIN,
50
51
  TEXT_STYLE_FIELDS,
51
52
  TINT_SCALE,
@@ -339,6 +340,7 @@ import {
339
340
  tempTintToXy,
340
341
  temperatureToKelvin,
341
342
  textMatrix,
343
+ textOrientation,
342
344
  textOutlines,
343
345
  textRange,
344
346
  toTextSpace,
@@ -384,7 +386,7 @@ import {
384
386
  writePsd,
385
387
  xyToTempTint,
386
388
  xyToUv
387
- } from "../chunk-TXYXF32N.js";
389
+ } from "../chunk-ZIDUPSP4.js";
388
390
  import {
389
391
  parseCssColor
390
392
  } from "../chunk-3CI7FRMK.js";
@@ -622,6 +624,7 @@ import {
622
624
  identityWarpMesh,
623
625
  invertMatrix,
624
626
  layoutText,
627
+ lineToTextSpace,
625
628
  multiplyMatrices,
626
629
  paragraphRanges,
627
630
  pullWarpMesh,
@@ -632,7 +635,10 @@ import {
632
635
  spliceRuns,
633
636
  styleAt,
634
637
  subpathsToBezier,
638
+ textArrowStep,
635
639
  textIndexAt,
640
+ textLineMove,
641
+ textSelectionQuads,
636
642
  translateMatrix,
637
643
  warpMeshColumns,
638
644
  warpMeshEditPoints,
@@ -640,7 +646,7 @@ import {
640
646
  warpMeshParamAt,
641
647
  warpMeshRows,
642
648
  warpPresetMesh
643
- } from "../chunk-LPIKXPBM.js";
649
+ } from "../chunk-GHCXLQ47.js";
644
650
  import "../chunk-YXKLVD56.js";
645
651
  import "../chunk-M6DNZNVY.js";
646
652
  import {
@@ -2704,7 +2710,11 @@ var TextEditSession = class {
2704
2710
  if (dir > 0 && c >= 55296 && c <= 56319 && i + 1 < t.length) return 2;
2705
2711
  return 1;
2706
2712
  }
2707
- /** Moves the caret (Shift extends the selection). */
2713
+ /**
2714
+ * Moves the caret (Shift extends the selection): `left` / `right` along the line, `up` / `down`
2715
+ * between lines, `home` / `end` of the line, `start` / `finish` of the text. Arrow keys of vertical
2716
+ * text map onto these through `textArrowStep` in `handleKey`.
2717
+ */
2708
2718
  move(to, extend = false) {
2709
2719
  const n = this.text.length;
2710
2720
  let f = this.focus;
@@ -2723,15 +2733,7 @@ var TextEditSession = class {
2723
2733
  const last = line.chars[line.chars.length - 1];
2724
2734
  f = last ? Math.min(n, last.index + 1) : line.start;
2725
2735
  if (last && this.text[last.index] === " " && c.line < layout.lines.length - 1) f = last.index;
2726
- } else {
2727
- const target = layout.lines[c.line + (to === "up" ? -1 : 1)];
2728
- if (!target) f = to === "up" ? 0 : n;
2729
- else {
2730
- const hit = target.chars.find((ch) => c.x < ch.x + ch.advance / 2);
2731
- const last = target.chars[target.chars.length - 1];
2732
- f = hit ? hit.index : last ? last.index + 1 : target.start;
2733
- }
2734
- }
2736
+ } else f = textLineMove(layout, f, to === "up" ? -1 : 1, n);
2735
2737
  }
2736
2738
  }
2737
2739
  this.focus = f;
@@ -2767,17 +2769,16 @@ var TextEditSession = class {
2767
2769
  this.insert("\n");
2768
2770
  return true;
2769
2771
  case "ArrowLeft":
2770
- this.move(mod2 ? "home" : "left", e.shiftKey);
2771
- return true;
2772
2772
  case "ArrowRight":
2773
- this.move(mod2 ? "end" : "right", e.shiftKey);
2774
- return true;
2775
2773
  case "ArrowUp":
2776
- this.move(mod2 ? "start" : "up", e.shiftKey);
2777
- return true;
2778
- case "ArrowDown":
2779
- this.move(mod2 ? "finish" : "down", e.shiftKey);
2774
+ case "ArrowDown": {
2775
+ const step = textArrowStep(this.layer.orientation, e.key);
2776
+ if (step === "previous") this.move(mod2 ? "home" : "left", e.shiftKey);
2777
+ else if (step === "next") this.move(mod2 ? "end" : "right", e.shiftKey);
2778
+ else if (step === "line-before") this.move(mod2 ? "start" : "up", e.shiftKey);
2779
+ else this.move(mod2 ? "finish" : "down", e.shiftKey);
2780
2780
  return true;
2781
+ }
2781
2782
  case "Home":
2782
2783
  this.move("home", e.shiftKey);
2783
2784
  return true;
@@ -2829,20 +2830,9 @@ var TextEditSession = class {
2829
2830
  frame = [at(b.x, b.y), at(b.x + b.width, b.y), at(b.x + b.width, b.y + b.height), at(b.x, b.y + b.height)];
2830
2831
  }
2831
2832
  if (!layout) return { caret: null, selection: [], frame };
2832
- const selection = [];
2833
- if (this.start !== this.end) {
2834
- for (const l of layout.lines) {
2835
- const chars = l.chars.filter((c2) => c2.index >= this.start && c2.index < this.end);
2836
- if (!chars.length) continue;
2837
- const x0 = chars[0].x;
2838
- const x1 = chars[chars.length - 1].x + chars[chars.length - 1].advance;
2839
- const top = l.baseline - l.ascent;
2840
- const bottom = l.baseline + l.descent;
2841
- selection.push([at(x0, top), at(x1, top), at(x1, bottom), at(x0, bottom)]);
2842
- }
2843
- }
2833
+ const selection = textSelectionQuads(layout, this.start, this.end).map((q) => q.map((p) => at(p.x, p.y)));
2844
2834
  const c = caretAt(layout, this.focus);
2845
- return { caret: [at(c.x, c.top), at(c.x, c.bottom)], selection, frame };
2835
+ return { caret: [at(c.from.x, c.from.y), at(c.to.x, c.to.y)], selection, frame };
2846
2836
  }
2847
2837
  /** Ends editing: an empty layer made for this session is deleted (as Photoshop does). Returns whether the layer remains. */
2848
2838
  close() {
@@ -2939,6 +2929,7 @@ var TypeToolGesture = class {
2939
2929
  ...box ? { box } : {},
2940
2930
  style: { fontFamily: o.fontFamily, fontSize: o.fontSize, fontWeight: o.fontWeight, italic: o.italic, color: o.color },
2941
2931
  paragraph: o.align !== "left" ? { align: o.align } : {},
2932
+ ...o.orientation === "vertical" ? { orientation: "vertical" } : {},
2942
2933
  name: "Text"
2943
2934
  });
2944
2935
  this.session = new TextEditSession(this.controller, id, 0);
@@ -9328,6 +9319,7 @@ var ImageEditorController = class {
9328
9319
  runs: ranges(layer.runs),
9329
9320
  paragraphs: ranges(layer.paragraphs),
9330
9321
  frame: { ...layer.frame },
9322
+ orientation: layer.orientation ?? "horizontal",
9331
9323
  transform: [...layer.transform ?? [1, 0, 0, 1, 0, 0]],
9332
9324
  lines,
9333
9325
  bounds: this.getLayerBounds(id),
@@ -9361,23 +9353,16 @@ var ImageEditorController = class {
9361
9353
  /**
9362
9354
  * Type Mask (horizontal or vertical): a selection in the shape of `text`, laid out and drawn as
9363
9355
  * `addTextLayer` would place it (font, size, tracking, box, rotation), combined with the current
9364
- * selection by `mode`. Vertical type stacks the characters top to bottom, centred on `x`. No
9365
- * layer is added. One undo step. Returns whether anything is selected.
9356
+ * selection by `mode`. Vertical type is laid out as vertical type layers are: columns down from
9357
+ * (`x`, `y`), right to left, CJK upright and Latin turned. No layer is added. One undo step. Returns whether anything is selected.
9366
9358
  */
9367
9359
  selectTextShape(init) {
9368
9360
  const vertical = init.orientation === "vertical";
9369
9361
  if (init.orientation !== void 0 && init.orientation !== "horizontal" && !vertical) throw new LayerOperationError("orientation must be horizontal or vertical.");
9370
9362
  if (init.feather !== void 0 && !(init.feather >= 0 && init.feather <= 1e3)) throw new LayerOperationError("feather must be from 0 to 1000 px.");
9371
- let text = normalizeText(init.text);
9363
+ const text = normalizeText(init.text);
9372
9364
  if (!text.trim()) throw new LayerOperationError("The text is empty, so there is nothing to select; give some characters.");
9373
- let paragraph = init.paragraph;
9374
- if (vertical) {
9375
- if (/\n/.test(text)) throw new LayerOperationError("Vertical type masks take one column; select each column separately (mode add) instead of line breaks.");
9376
- if (init.box) throw new LayerOperationError("Vertical type masks are point text; leave out box.");
9377
- text = Array.from(text).join("\n");
9378
- paragraph = { align: "center", ...paragraph ?? {} };
9379
- }
9380
- const layer = this.layoutTypeLayer({ ...init, text, paragraph });
9365
+ const layer = this.layoutTypeLayer({ ...init, text, orientation: vertical ? "vertical" : "horizontal" });
9381
9366
  const { width, height } = this.naturalSize;
9382
9367
  const b = contentBounds(layer.surface);
9383
9368
  const x0 = Math.max(0, b?.x ?? 0);
@@ -9412,10 +9397,11 @@ var ImageEditorController = class {
9412
9397
  if (!(Number.isFinite(width) && width >= 1 && Number.isFinite(height) && height >= 1)) throw new LayerOperationError("box.width and box.height must be at least 1 pixel.");
9413
9398
  frame = { kind: "box", width, height };
9414
9399
  }
9400
+ const orientation = init.orientation === void 0 ? "horizontal" : textOrientation(init.orientation);
9415
9401
  if (init.rotation !== void 0 && !Number.isFinite(init.rotation)) throw new LayerOperationError("rotation must be a number of degrees.");
9416
9402
  const t = [1, 0, 0, 1, init.x, init.y];
9417
9403
  const transform = init.rotation ? multiplyMatrices(t, rotateMatrix(init.rotation, { x: init.x, y: init.y })) : t;
9418
- return createTypeLayer({ text, runs: [{ length: text.length, style }], paragraphs: [{ length: text.length, style: paragraph }], frame, transform, name: init.name ?? typeLayerName(text) }, this.textEnv());
9404
+ return createTypeLayer({ text, runs: [{ length: text.length, style }], paragraphs: [{ length: text.length, style: paragraph }], frame, orientation, transform, name: init.name ?? typeLayerName(text) }, this.textEnv());
9419
9405
  }
9420
9406
  /**
9421
9407
  * Replaces text [start, end) (default all of it) with `text`; inserted text takes the style at
@@ -9490,14 +9476,27 @@ var ImageEditorController = class {
9490
9476
  this.state.layers,
9491
9477
  id,
9492
9478
  (l) => {
9493
- if (frame.kind === "box" && l.frame.kind === "box") return { frame: { kind: "box", width: frame.width, height: frame.height } };
9494
- if (!shaper) throw new LayerOperationError("Changing between point and paragraph text needs a text shaper to measure the text.");
9495
- const lines = layoutText(l, shaper).lines;
9496
- const first = lines[0];
9497
- const dx = frame.kind === "box" ? first ? first.x : 0 : 0;
9498
- const dy = frame.kind === "box" ? first ? first.baseline - first.ascent : 0 : first ? first.baseline : 0;
9499
9479
  const m = textMatrix(l);
9500
- const shifted = [m[0], m[1], m[2], m[3], m[0] * dx + m[2] * dy + m[4], m[1] * dx + m[3] * dy + m[5]];
9480
+ const shift = (dx2, dy2) => [m[0], m[1], m[2], m[3], m[0] * dx2 + m[2] * dy2 + m[4], m[1] * dx2 + m[3] * dy2 + m[5]];
9481
+ if (frame.kind === "box" && l.frame.kind === "box") {
9482
+ const resized = { frame: { kind: "box", width: frame.width, height: frame.height } };
9483
+ if (l.orientation === "vertical" && frame.width !== l.frame.width) resized.transform = shift(l.frame.width - frame.width, 0);
9484
+ return resized;
9485
+ }
9486
+ if (!shaper) throw new LayerOperationError("Changing between point and paragraph text needs a text shaper to measure the text.");
9487
+ const layout = layoutText(l, shaper);
9488
+ const first = layout.lines[0];
9489
+ let dx;
9490
+ let dy;
9491
+ if (l.orientation === "vertical") {
9492
+ const at = !first ? { x: 0, y: 0 } : frame.kind === "box" ? lineToTextSpace(layout, { x: first.x, y: first.baseline - first.ascent }) : lineToTextSpace(layout, { x: 0, y: first.baseline });
9493
+ dx = frame.kind === "box" ? at.x - frame.width : at.x;
9494
+ dy = at.y;
9495
+ } else {
9496
+ dx = frame.kind === "box" ? first ? first.x : 0 : 0;
9497
+ dy = frame.kind === "box" ? first ? first.baseline - first.ascent : 0 : first ? first.baseline : 0;
9498
+ }
9499
+ const shifted = shift(dx, dy);
9501
9500
  const nextFrame = frame.kind === "box" ? { kind: "box", width: frame.width, height: frame.height } : { kind: "point" };
9502
9501
  return { frame: nextFrame, transform: shifted };
9503
9502
  },
@@ -9507,6 +9506,25 @@ var ImageEditorController = class {
9507
9506
  this.commitLayers(layers, void 0, commitToHistory);
9508
9507
  return this.typeInfo(id);
9509
9508
  }
9509
+ /**
9510
+ * Horizontal ↔ vertical type (Type › Orientation): the text, styles, frame and origin stay; the
9511
+ * lines become columns running down, stacked right to left, or back. One undo step. Returns the
9512
+ * layer.
9513
+ */
9514
+ setTextOrientation(id, orientation, commitToHistory = true) {
9515
+ const next = textOrientation(orientation);
9516
+ const layer = requireTypeLayer(this.state.layers, id);
9517
+ if ((layer.orientation ?? "horizontal") === next) return this.typeInfo(id);
9518
+ const { layers } = updateTypeLayer(
9519
+ this.state.layers,
9520
+ id,
9521
+ () => ({ orientation: next === "vertical" ? "vertical" : void 0 }),
9522
+ this.textEnv(),
9523
+ "change its orientation"
9524
+ );
9525
+ this.commitLayers(layers, void 0, commitToHistory);
9526
+ return this.typeInfo(id);
9527
+ }
9510
9528
  /**
9511
9529
  * Convert to Shape: the text's glyph outlines become a shape layer with the same id, name and
9512
9530
  * layer properties (needs a shaper that gives outlines). The fill is the first run's colour;
@@ -9552,8 +9570,8 @@ var ImageEditorController = class {
9552
9570
  if (!layout) return null;
9553
9571
  const c = caretAt(layout, Math.max(0, Math.min(layer.text.length, index)));
9554
9572
  const m = textMatrix(layer);
9555
- const at = (x, y) => ({ x: m[0] * x + m[2] * y + m[4], y: m[1] * x + m[3] * y + m[5] });
9556
- return { top: at(c.x, c.top), bottom: at(c.x, c.bottom), line: c.line };
9573
+ const at = (p) => ({ x: m[0] * p.x + m[2] * p.y + m[4], y: m[1] * p.x + m[3] * p.y + m[5] });
9574
+ return { top: at(c.from), bottom: at(c.to), line: c.line };
9557
9575
  }
9558
9576
  // --- Shape layers ---
9559
9577
  /** What shape rendering needs: the canvas size and the document's patterns. */
@@ -11302,7 +11320,7 @@ var DEPTH_MASK_CONTROLS = [
11302
11320
  var IMAGE_PLAYBACK_KIND = "layer";
11303
11321
  var PAINT = /^(paint_stroke|clone_stamp|heal_brush|spot_heal|dodge|burn|sponge|smudge|blur_stroke|sharpen_stroke|history_brush|set_clone_source|set_clone_transform|fill_pixels|clear_pixels|set_paint|set_retouch_options|load_mixer_brush|clean_mixer_brush)$/;
11304
11322
  var SELECT = /^(select_region|select_subject|select_by_color|select_all|deselect|invert_selection|select_rect|select_ellipse|select_polygon|select_line|magic_wand|grow_selection|select_similar|reselect|select_layer_transparency|select_color_range|load_selection_from_image|load_selection_from_mask|set_selection_display|modify_selection|refine_selection|transform_selection|apply_selection_as_mask|layer_via_copy|stroke_selection|content_aware_fill|copy_pixels|cut_pixels|paste_pixels|save_selection|load_selection_from_channel|set_channel_properties|duplicate_channel|delete_channel|load_channel_from_image|set_quick_mask|path_to_selection|select_text_shape)$/;
11305
- var ANNOTATE = /^(add_shape_layer|update_shape|add_shape_component|set_shape_component|remove_shape_component|merge_shape_components|add_text_layer|set_text|set_text_style|set_paragraph_style|set_text_frame|convert_text_to_shape)$/;
11323
+ var ANNOTATE = /^(add_shape_layer|update_shape|add_shape_component|set_shape_component|remove_shape_component|merge_shape_components|add_text_layer|set_text|set_text_style|set_paragraph_style|set_text_frame|set_text_orientation|convert_text_to_shape)$/;
11306
11324
  var CROP = /^(set_crop|crop_to_selection|reset_crop|set_rotation|flip_image|transform_layer|warp_layer|flip_layer|offset_layer)$/;
11307
11325
  var ADJUST = /^(set_adjustments|add_adjustment_layer|update_adjustment_layer|remove_adjustment_layer|move_adjustment_layer)$/;
11308
11326
  function imagePlaybackPanel(tool) {
@@ -12903,6 +12921,7 @@ function describeLayer(layer, activeId, boundsOf) {
12903
12921
  out.text = {
12904
12922
  text: layer.text.length > 80 ? `${layer.text.slice(0, 80)}\u2026` : layer.text,
12905
12923
  frame: layer.frame.kind,
12924
+ ...layer.orientation === "vertical" ? { orientation: "vertical" } : {},
12906
12925
  runs: layer.runs.length,
12907
12926
  rendering: layer.rendering === "stored" ? "stored" : "live",
12908
12927
  missingFonts: layer.missingFonts ?? []
@@ -16254,7 +16273,13 @@ var STYLE = {
16254
16273
  leading: { type: ["number", "null"], minimum: 0, maximum: 1e4, description: "Baseline-to-baseline distance in pixels (null = auto, the paragraph autoLeading \xD7 size)." },
16255
16274
  baselineShift: { type: ["number", "null"], minimum: -5e3, maximum: 5e3, description: "Pixels; positive raises the text (null resets to 0)." },
16256
16275
  underline: { type: "boolean", description: "Underline." },
16257
- strikethrough: { type: "boolean", description: "Strike through." }
16276
+ strikethrough: { type: "boolean", description: "Strike through." },
16277
+ upright: { type: "boolean", description: "Vertical text only: set Latin and other horizontal-script characters upright, one under the other, instead of turned sideways (default false)." }
16278
+ };
16279
+ var ORIENTATION = {
16280
+ type: "string",
16281
+ enum: ["horizontal", "vertical"],
16282
+ description: "horizontal (default): lines left to right, stacked down. vertical: columns top to bottom, stacked right to left; CJK stands upright, Latin turns sideways unless styled upright."
16258
16283
  };
16259
16284
  var PARAGRAPH = {
16260
16285
  align: { type: "string", enum: ["left", "center", "right", "justify"], description: "Alignment (justify stretches paragraph-box lines but the last)." },
@@ -16293,7 +16318,7 @@ function createImageTypeTools(controller) {
16293
16318
  const get = {
16294
16319
  name: "get_text_layer",
16295
16320
  title: "Read a type layer",
16296
- description: "Returns a type layer\u2019s text, its character runs and paragraphs as [start, end) ranges in UTF-16 code units with their styles, the frame (point text, or a paragraph box with its size), the text-to-document transform, the laid-out lines (range, baseline, width), the rendered bounds, missing fonts and whether the pixels are live or stored from a file. Call before editing text you did not write, to get the ranges. Changes nothing.",
16321
+ description: "Returns a type layer\u2019s text, its character runs and paragraphs as [start, end) ranges in UTF-16 code units with their styles, the frame (point text, or a paragraph box with its size), the orientation (horizontal or vertical), the text-to-document transform, the laid-out lines (range, baseline, width), the rendered bounds, missing fonts and whether the pixels are live or stored from a file. Call before editing text you did not write, to get the ranges. Changes nothing.",
16297
16322
  inputSchema: { type: "object", properties: { layerId: LAYER_ID6 }, required: ["layerId"], additionalProperties: false },
16298
16323
  annotations: { title: "Read a type layer", ...READ11 },
16299
16324
  handler: ({ layerId }) => controller.getTextLayer(typeId(layerId))
@@ -16301,7 +16326,7 @@ function createImageTypeTools(controller) {
16301
16326
  const add2 = {
16302
16327
  name: "add_text_layer",
16303
16328
  title: "Add a type layer",
16304
- description: "Adds a live type layer and makes it active: point text whose origin (x, y) is the first line\u2019s baseline at its alignment edge, or paragraph text wrapped in box {width, height} with its top-left at (x, y). Line breaks in text start paragraphs. Style and paragraph settings apply to the whole text (change ranges later with set_text_style). Default style: 24 px sans-serif in the foreground colour. One undo step. Returns the layer and the text layer, including missingFonts.",
16329
+ description: "Adds a live type layer and makes it active: point text whose origin (x, y) is the first line\u2019s baseline at its alignment edge, or paragraph text wrapped in box {width, height} with its top-left at (x, y). orientation vertical sets columns running down from (x, y) (the top of the first column\u2019s centre line; a box fills from its right edge), stacked right to left. Line breaks in text start paragraphs. Style and paragraph settings apply to the whole text (change ranges later with set_text_style). Default style: 24 px sans-serif in the foreground colour. One undo step. Returns the layer and the text layer, including missingFonts.",
16305
16330
  inputSchema: {
16306
16331
  type: "object",
16307
16332
  properties: {
@@ -16317,6 +16342,7 @@ function createImageTypeTools(controller) {
16317
16342
  },
16318
16343
  style: { type: "object", description: "Character style.", properties: STYLE, additionalProperties: false },
16319
16344
  paragraph: { type: "object", description: "Paragraph style.", properties: PARAGRAPH, additionalProperties: false },
16345
+ orientation: ORIENTATION,
16320
16346
  rotation: { type: "number", description: "Degrees clockwise about the origin (default 0)." },
16321
16347
  name: { type: "string", description: "Layer name (default the start of the text)." },
16322
16348
  opacity: { type: "number", minimum: 0, maximum: 1, description: "Layer opacity 0..1 (default 1)." },
@@ -16331,7 +16357,7 @@ function createImageTypeTools(controller) {
16331
16357
  },
16332
16358
  annotations: { title: "Add a type layer", ...WRITE9 },
16333
16359
  handler: (args) => {
16334
- const init = pick2(args, ["text", "x", "y", "box", "style", "paragraph", "rotation", "name", "opacity", "blend", "aboveId", "belowId", "parentId", "index"]);
16360
+ const init = pick2(args, ["text", "x", "y", "box", "style", "paragraph", "orientation", "rotation", "name", "opacity", "blend", "aboveId", "belowId", "parentId", "index"]);
16335
16361
  if (init.blend !== void 0) init.blend = init.blend;
16336
16362
  const id = controller.addTextLayer(init);
16337
16363
  return { layer: layerSummary(id), text: controller.getTextLayer(id) };
@@ -16391,6 +16417,14 @@ function createImageTypeTools(controller) {
16391
16417
  return controller.setTextFrame(id, kind === "box" ? { kind: "box", width, height } : { kind: "point" });
16392
16418
  }
16393
16419
  };
16420
+ const setOrientation = {
16421
+ name: "set_text_orientation",
16422
+ title: "Horizontal or vertical type",
16423
+ description: "Type \u203A Orientation: sets a type layer horizontal (lines left to right) or vertical (columns top to bottom, right to left). The text, styles, frame and origin stay. One undo step. Returns the text layer with its orientation and new lines (columns).",
16424
+ inputSchema: { type: "object", properties: { layerId: LAYER_ID6, orientation: { ...ORIENTATION, description: "horizontal or vertical." } }, required: ["layerId", "orientation"], additionalProperties: false },
16425
+ annotations: { title: "Horizontal or vertical type", ...WRITE_IDEMPOTENT6 },
16426
+ handler: ({ layerId, orientation }) => controller.setTextOrientation(typeId(layerId), orientation)
16427
+ };
16394
16428
  const toShape = {
16395
16429
  name: "convert_text_to_shape",
16396
16430
  title: "Convert text to a shape",
@@ -16405,17 +16439,17 @@ function createImageTypeTools(controller) {
16405
16439
  const typeMask = {
16406
16440
  name: "select_text_shape",
16407
16441
  title: "Select the shape of text",
16408
- description: "Horizontal / Vertical Type Mask: selects the shape of text laid out as add_text_layer would place it (font family, size, weight, tracking, box, rotation; colour is ignored), combined with the current selection by mode. No layer is added. Vertical stacks the characters top to bottom, centred on x (one column; add more with mode add). Use it to cut text out of an image (layer_via_copy), fill letters with a photo (add_layer_mask), or mask an adjustment. Check fonts with list_fonts first. One undo step. Returns the selection.",
16442
+ description: "Horizontal / Vertical Type Mask: selects the shape of text laid out as add_text_layer would place it (font family, size, weight, tracking, box, rotation; colour is ignored), combined with the current selection by mode. No layer is added. Vertical lays the text out as vertical type: columns down from (x, y), stacked right to left, CJK upright and Latin turned sideways. Use it to cut text out of an image (layer_via_copy), fill letters with a photo (add_layer_mask), or mask an adjustment. Check fonts with list_fonts first. One undo step. Returns the selection.",
16409
16443
  inputSchema: {
16410
16444
  type: "object",
16411
16445
  properties: {
16412
- text: { type: "string", minLength: 1, description: "The text; \\n starts a new line (horizontal only)." },
16413
- x: { type: "number", description: "Document x of the origin, pixels (vertical: the column centre)." },
16414
- y: { type: "number", description: "Document y of the origin (the first baseline), pixels." },
16415
- orientation: { type: "string", enum: ["horizontal", "vertical"], description: "horizontal (default) or vertical (characters stacked top to bottom)." },
16446
+ text: { type: "string", minLength: 1, description: "The text; \\n starts a new line (vertical: a new column)." },
16447
+ x: { type: "number", description: "Document x of the origin, pixels (vertical: the first column\u2019s centre)." },
16448
+ y: { type: "number", description: "Document y of the origin, pixels (horizontal: the first baseline; vertical: the top of the first column)." },
16449
+ orientation: { ...ORIENTATION, description: "horizontal (default) or vertical: columns top to bottom, right to left, as vertical type layers (CJK upright, Latin turned sideways unless styled upright)." },
16416
16450
  box: {
16417
16451
  type: "object",
16418
- description: "Horizontal only: wrap in this box, pixels.",
16452
+ description: "Wrap in this box, pixels (vertical: columns fill it from its right edge).",
16419
16453
  properties: { width: { type: "number", minimum: 1, description: "Box width, pixels." }, height: { type: "number", minimum: 1, description: "Box height, pixels." } },
16420
16454
  required: ["width", "height"],
16421
16455
  additionalProperties: false
@@ -16438,7 +16472,7 @@ function createImageTypeTools(controller) {
16438
16472
  return { empty: !sel, bounds: sel?.bounds ?? null, area: Math.round(sel ? selectionArea(sel) : 0) };
16439
16473
  }
16440
16474
  };
16441
- return [listFonts, get, add2, setText, setStyle, setParagraph, setFrame, toShape, typeMask];
16475
+ return [listFonts, get, add2, setText, setStyle, setParagraph, setFrame, setOrientation, toShape, typeMask];
16442
16476
  }
16443
16477
 
16444
16478
  // src/image-editor/tools.ts
@@ -18577,6 +18611,7 @@ export {
18577
18611
  StrokeCoverage,
18578
18612
  SurfaceDraft,
18579
18613
  TEXT_ALIGNS,
18614
+ TEXT_ORIENTATIONS,
18580
18615
  TEXT_RENDER_MARGIN,
18581
18616
  TEXT_STYLE_FIELDS,
18582
18617
  TILE,
@@ -19310,6 +19345,7 @@ export {
19310
19345
  temperatureToKelvin,
19311
19346
  textIndexAt,
19312
19347
  textMatrix,
19348
+ textOrientation,
19313
19349
  textOutlines,
19314
19350
  textRange,
19315
19351
  tileCoord,
@@ -298,8 +298,8 @@ export interface ShapeLayer extends LayerBase {
298
298
  annotation?: Annotation;
299
299
  psd?: ShapePsdData;
300
300
  }
301
- export type { TextStyle, TextRun, TextAlign, ParagraphStyle, ParagraphRun } from '../../text/types.cjs';
302
- export { TEXT_ALIGNS } from '../../text/types.cjs';
301
+ export type { TextStyle, TextRun, TextAlign, TextOrientation, ParagraphStyle, ParagraphRun } from '../../text/types.cjs';
302
+ export { TEXT_ALIGNS, TEXT_ORIENTATIONS } from '../../text/types.cjs';
303
303
  /** PSD data of a type layer kept for round trips (see the PSD module). */
304
304
  export interface TypePsdData {
305
305
  /** The `TySh` block as read: written back while the layer is unchanged, else patched. */
@@ -338,6 +338,11 @@ export interface TypeLayer extends LayerBase {
338
338
  width: number;
339
339
  height: number;
340
340
  };
341
+ /**
342
+ * Missing = horizontal. `vertical`: columns running down, stacked right to left (point text:
343
+ * (0, 0) is the top of the first column's centre line; a box fills from its right edge).
344
+ */
345
+ orientation?: 'vertical';
341
346
  /** Text space → document (missing = identity). */
342
347
  transform?: AffineMatrix;
343
348
  /** Default true. */
@@ -298,8 +298,8 @@ export interface ShapeLayer extends LayerBase {
298
298
  annotation?: Annotation;
299
299
  psd?: ShapePsdData;
300
300
  }
301
- export type { TextStyle, TextRun, TextAlign, ParagraphStyle, ParagraphRun } from '../../text/types.js';
302
- export { TEXT_ALIGNS } from '../../text/types.js';
301
+ export type { TextStyle, TextRun, TextAlign, TextOrientation, ParagraphStyle, ParagraphRun } from '../../text/types.js';
302
+ export { TEXT_ALIGNS, TEXT_ORIENTATIONS } from '../../text/types.js';
303
303
  /** PSD data of a type layer kept for round trips (see the PSD module). */
304
304
  export interface TypePsdData {
305
305
  /** The `TySh` block as read: written back while the layer is unchanged, else patched. */
@@ -338,6 +338,11 @@ export interface TypeLayer extends LayerBase {
338
338
  width: number;
339
339
  height: number;
340
340
  };
341
+ /**
342
+ * Missing = horizontal. `vertical`: columns running down, stacked right to left (point text:
343
+ * (0, 0) is the top of the first column's centre line; a box fills from its right edge).
344
+ */
345
+ orientation?: 'vertical';
341
346
  /** Text space → document (missing = identity). */
342
347
  transform?: AffineMatrix;
343
348
  /** Default true. */
@@ -195,6 +195,8 @@ export interface SerializedTypeLayer extends SerializedLayerBase {
195
195
  runs: TextRun[];
196
196
  paragraphs: ParagraphRun[];
197
197
  frame: TypeLayer['frame'];
198
+ /** Missing: horizontal. */
199
+ orientation?: 'vertical';
198
200
  transform?: number[];
199
201
  antiAlias?: false;
200
202
  fillOpacity?: number;
@@ -195,6 +195,8 @@ export interface SerializedTypeLayer extends SerializedLayerBase {
195
195
  runs: TextRun[];
196
196
  paragraphs: ParagraphRun[];
197
197
  frame: TypeLayer['frame'];
198
+ /** Missing: horizontal. */
199
+ orientation?: 'vertical';
198
200
  transform?: number[];
199
201
  antiAlias?: false;
200
202
  fillOpacity?: number;
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import type { ImageEditorController, TypeLayerInfo } from '../controller.cjs';
8
8
  import type { ImagePoint } from '../types.cjs';
9
- import { type LiveShapeKind, type ParagraphStyle, type TextAlign, type TextStyle } from './model.cjs';
9
+ import { type LiveShapeKind, type ParagraphStyle, type TextAlign, type TextOrientation, type TextStyle } from './model.cjs';
10
10
  /** What the shape tool draws next (and what its options bar edits on a selected shape). */
11
11
  export interface ShapeToolOptions {
12
12
  kind: LiveShapeKind;
@@ -36,6 +36,8 @@ export interface TypeToolOptions {
36
36
  italic: boolean;
37
37
  color: string;
38
38
  align: TextAlign;
39
+ /** Horizontal Type or Vertical Type tool (missing = horizontal): what new text is set as. */
40
+ orientation?: TextOrientation;
39
41
  }
40
42
  export declare const DEFAULT_TYPE_TOOL_OPTIONS: TypeToolOptions;
41
43
  /** A live shape for a drag from `a` to `b` (Shift: square / circle / 45° line; Alt: from the centre). */
@@ -107,7 +109,11 @@ export declare class TextEditSession {
107
109
  deleteForward(): void;
108
110
  /** 2 when the code unit at `i` is half of a surrogate pair (moving `dir`), else 1. */
109
111
  private surrogate;
110
- /** Moves the caret (Shift extends the selection). */
112
+ /**
113
+ * Moves the caret (Shift extends the selection): `left` / `right` along the line, `up` / `down`
114
+ * between lines, `home` / `end` of the line, `start` / `finish` of the text. Arrow keys of vertical
115
+ * text map onto these through `textArrowStep` in `handleKey`.
116
+ */
111
117
  move(to: 'left' | 'right' | 'up' | 'down' | 'home' | 'end' | 'start' | 'finish', extend?: boolean): void;
112
118
  selectAll(): void;
113
119
  /** Places the caret at a document point (Shift-click extends). */
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import type { ImageEditorController, TypeLayerInfo } from '../controller.js';
8
8
  import type { ImagePoint } from '../types.js';
9
- import { type LiveShapeKind, type ParagraphStyle, type TextAlign, type TextStyle } from './model.js';
9
+ import { type LiveShapeKind, type ParagraphStyle, type TextAlign, type TextOrientation, type TextStyle } from './model.js';
10
10
  /** What the shape tool draws next (and what its options bar edits on a selected shape). */
11
11
  export interface ShapeToolOptions {
12
12
  kind: LiveShapeKind;
@@ -36,6 +36,8 @@ export interface TypeToolOptions {
36
36
  italic: boolean;
37
37
  color: string;
38
38
  align: TextAlign;
39
+ /** Horizontal Type or Vertical Type tool (missing = horizontal): what new text is set as. */
40
+ orientation?: TextOrientation;
39
41
  }
40
42
  export declare const DEFAULT_TYPE_TOOL_OPTIONS: TypeToolOptions;
41
43
  /** A live shape for a drag from `a` to `b` (Shift: square / circle / 45° line; Alt: from the centre). */
@@ -107,7 +109,11 @@ export declare class TextEditSession {
107
109
  deleteForward(): void;
108
110
  /** 2 when the code unit at `i` is half of a surrogate pair (moving `dir`), else 1. */
109
111
  private surrogate;
110
- /** Moves the caret (Shift extends the selection). */
112
+ /**
113
+ * Moves the caret (Shift extends the selection): `left` / `right` along the line, `up` / `down`
114
+ * between lines, `home` / `end` of the line, `start` / `finish` of the text. Arrow keys of vertical
115
+ * text map onto these through `textArrowStep` in `handleKey`.
116
+ */
111
117
  move(to: 'left' | 'right' | 'up' | 'down' | 'home' | 'end' | 'start' | 'finish', extend?: boolean): void;
112
118
  selectAll(): void;
113
119
  /** Places the caret at a document point (Shift-click extends). */
@@ -16,7 +16,7 @@ import type { AffineMatrix } from '../../geom/types.cjs';
16
16
  import { type BezierPath } from '../../canvas/pathops/bezier.cjs';
17
17
  import { type ImageLayer, type ParagraphRun, type ParagraphStyle, type PixelLayer, type TextRun, type TextStyle, type TypeLayer } from './model.cjs';
18
18
  import { caretAt, DEFAULT_AUTO_LEADING, DEFAULT_TEXT_STYLE, fitParagraphRuns, fitRuns, fontOf, layoutText, paragraphRanges, restyleRange, spliceRuns, styleAt, textIndexAt, type LaidChar, type LaidFragment, type LaidLine, type TextLayout } from '../../text/layout.cjs';
19
- import type { TextFont, TextShaper } from '../../text/types.cjs';
19
+ import { type TextFont, type TextOrientation, type TextShaper } from '../../text/types.cjs';
20
20
  export { caretAt, DEFAULT_AUTO_LEADING, DEFAULT_TEXT_STYLE, fitParagraphRuns, fitRuns, fontOf, layoutText, paragraphRanges, restyleRange, spliceRuns, styleAt, textIndexAt };
21
21
  export type { LaidChar, LaidFragment, LaidLine, TextFont, TextLayout, TextShaper };
22
22
  /** What rendering a type layer needs besides the layer. */
@@ -48,7 +48,7 @@ export declare function renderText(layer: TypeLayer, env: TextEnv): {
48
48
  /** The layer drawn again (`rendering` and `missingFonts` updated); refuses when nothing can draw it. */
49
49
  export declare function rerenderText(layer: TypeLayer, env: TextEnv): TypeLayer;
50
50
  /** Fields of `TextStyle` an edit can set (`null` clears an optional one). */
51
- export declare const TEXT_STYLE_FIELDS: readonly ["fontFamily", "fontWeight", "italic", "fontSize", "color", "opacity", "tracking", "leading", "baselineShift", "underline", "strikethrough", "postScriptName"];
51
+ export declare const TEXT_STYLE_FIELDS: readonly ["fontFamily", "fontWeight", "italic", "fontSize", "color", "opacity", "tracking", "leading", "baselineShift", "underline", "strikethrough", "upright", "postScriptName"];
52
52
  /** `base` with the given style fields changed, validated (`null` clears leading, tracking, …). */
53
53
  export declare function patchTextStyle(base: TextStyle, patch: Record<string, unknown>, path?: string): TextStyle;
54
54
  export declare const PARAGRAPH_STYLE_FIELDS: readonly ["align", "autoLeading", "firstLineIndent", "startIndent", "endIndent", "spaceBefore", "spaceAfter"];
@@ -67,9 +67,13 @@ export interface TypeLayerData {
67
67
  runs: TextRun[];
68
68
  paragraphs?: ParagraphRun[];
69
69
  frame: TypeLayer['frame'];
70
+ /** Default horizontal. */
71
+ orientation?: TextOrientation;
70
72
  transform?: AffineMatrix;
71
73
  name?: string;
72
74
  }
75
+ /** An orientation from loose input (`horizontal` or `vertical`). */
76
+ export declare function textOrientation(v: unknown, path?: string): TextOrientation;
73
77
  /**
74
78
  * A new type layer, laid out and drawn. Without anything to draw it, refused, or with `lenient`
75
79
  * kept undrawn (`rendering: 'stored'`, no pixels) until a shaper draws it.
@@ -16,7 +16,7 @@ import type { AffineMatrix } from '../../geom/types.js';
16
16
  import { type BezierPath } from '../../canvas/pathops/bezier.js';
17
17
  import { type ImageLayer, type ParagraphRun, type ParagraphStyle, type PixelLayer, type TextRun, type TextStyle, type TypeLayer } from './model.js';
18
18
  import { caretAt, DEFAULT_AUTO_LEADING, DEFAULT_TEXT_STYLE, fitParagraphRuns, fitRuns, fontOf, layoutText, paragraphRanges, restyleRange, spliceRuns, styleAt, textIndexAt, type LaidChar, type LaidFragment, type LaidLine, type TextLayout } from '../../text/layout.js';
19
- import type { TextFont, TextShaper } from '../../text/types.js';
19
+ import { type TextFont, type TextOrientation, type TextShaper } from '../../text/types.js';
20
20
  export { caretAt, DEFAULT_AUTO_LEADING, DEFAULT_TEXT_STYLE, fitParagraphRuns, fitRuns, fontOf, layoutText, paragraphRanges, restyleRange, spliceRuns, styleAt, textIndexAt };
21
21
  export type { LaidChar, LaidFragment, LaidLine, TextFont, TextLayout, TextShaper };
22
22
  /** What rendering a type layer needs besides the layer. */
@@ -48,7 +48,7 @@ export declare function renderText(layer: TypeLayer, env: TextEnv): {
48
48
  /** The layer drawn again (`rendering` and `missingFonts` updated); refuses when nothing can draw it. */
49
49
  export declare function rerenderText(layer: TypeLayer, env: TextEnv): TypeLayer;
50
50
  /** Fields of `TextStyle` an edit can set (`null` clears an optional one). */
51
- export declare const TEXT_STYLE_FIELDS: readonly ["fontFamily", "fontWeight", "italic", "fontSize", "color", "opacity", "tracking", "leading", "baselineShift", "underline", "strikethrough", "postScriptName"];
51
+ export declare const TEXT_STYLE_FIELDS: readonly ["fontFamily", "fontWeight", "italic", "fontSize", "color", "opacity", "tracking", "leading", "baselineShift", "underline", "strikethrough", "upright", "postScriptName"];
52
52
  /** `base` with the given style fields changed, validated (`null` clears leading, tracking, …). */
53
53
  export declare function patchTextStyle(base: TextStyle, patch: Record<string, unknown>, path?: string): TextStyle;
54
54
  export declare const PARAGRAPH_STYLE_FIELDS: readonly ["align", "autoLeading", "firstLineIndent", "startIndent", "endIndent", "spaceBefore", "spaceAfter"];
@@ -67,9 +67,13 @@ export interface TypeLayerData {
67
67
  runs: TextRun[];
68
68
  paragraphs?: ParagraphRun[];
69
69
  frame: TypeLayer['frame'];
70
+ /** Default horizontal. */
71
+ orientation?: TextOrientation;
70
72
  transform?: AffineMatrix;
71
73
  name?: string;
72
74
  }
75
+ /** An orientation from loose input (`horizontal` or `vertical`). */
76
+ export declare function textOrientation(v: unknown, path?: string): TextOrientation;
73
77
  /**
74
78
  * A new type layer, laid out and drawn. Without anything to draw it, refused, or with `lenient`
75
79
  * kept undrawn (`rendering: 'stored'`, no pixels) until a shaper draws it.
@@ -25,6 +25,7 @@ export interface PsdTypeData {
25
25
  runs: TextRun[];
26
26
  paragraphs: ParagraphRun[];
27
27
  frame: TypeLayer['frame'];
28
+ orientation: 'horizontal' | 'vertical';
28
29
  transform: AffineMatrix;
29
30
  antiAlias: boolean;
30
31
  /** PostScript names the text uses. */
@@ -33,7 +34,7 @@ export interface PsdTypeData {
33
34
  /** A type layer's data from a `TySh` block, or `null` when the block can't be read. `notes` collects approximations. */
34
35
  export declare function typeFromTySh(data: Uint8Array, notes: Set<string>): PsdTypeData | null;
35
36
  /** What a type layer says, for deciding whether a `TySh` read from a file still describes it. */
36
- export declare function typeSignature(layer: Pick<TypeLayer, 'text' | 'runs' | 'paragraphs' | 'frame' | 'transform' | 'antiAlias'>): string;
37
+ export declare function typeSignature(layer: Pick<TypeLayer, 'text' | 'runs' | 'paragraphs' | 'frame' | 'orientation' | 'transform' | 'antiAlias'>): string;
37
38
  /** EngineData for a layer, patched into `template` (from the file) when there is one. */
38
39
  export declare function buildEngineData(layer: TypeLayer, template: EngineValue | null): EngineValue;
39
40
  /** The `TySh` block for a type layer: the one read while unchanged, else patched or built. */
@@ -25,6 +25,7 @@ export interface PsdTypeData {
25
25
  runs: TextRun[];
26
26
  paragraphs: ParagraphRun[];
27
27
  frame: TypeLayer['frame'];
28
+ orientation: 'horizontal' | 'vertical';
28
29
  transform: AffineMatrix;
29
30
  antiAlias: boolean;
30
31
  /** PostScript names the text uses. */
@@ -33,7 +34,7 @@ export interface PsdTypeData {
33
34
  /** A type layer's data from a `TySh` block, or `null` when the block can't be read. `notes` collects approximations. */
34
35
  export declare function typeFromTySh(data: Uint8Array, notes: Set<string>): PsdTypeData | null;
35
36
  /** What a type layer says, for deciding whether a `TySh` read from a file still describes it. */
36
- export declare function typeSignature(layer: Pick<TypeLayer, 'text' | 'runs' | 'paragraphs' | 'frame' | 'transform' | 'antiAlias'>): string;
37
+ export declare function typeSignature(layer: Pick<TypeLayer, 'text' | 'runs' | 'paragraphs' | 'frame' | 'orientation' | 'transform' | 'antiAlias'>): string;
37
38
  /** EngineData for a layer, patched into `template` (from the file) when there is one. */
38
39
  export declare function buildEngineData(layer: TypeLayer, template: EngineValue | null): EngineValue;
39
40
  /** The `TySh` block for a type layer: the one read while unchanged, else patched or built. */