@pixerate/editor 0.191.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 (55) 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 +31 -2
  12. package/dist/image-editor/controller.d.ts +31 -2
  13. package/dist/image-editor/index.cjs +1064 -923
  14. package/dist/image-editor/index.js +204 -63
  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/selection/tool-options.d.cts +7 -1
  26. package/dist/image-editor/selection/tool-options.d.ts +7 -1
  27. package/dist/image-editor/tools.d.cts +1 -1
  28. package/dist/image-editor/tools.d.ts +1 -1
  29. package/dist/image-editor/type-tools.d.cts +2 -2
  30. package/dist/image-editor/type-tools.d.ts +2 -2
  31. package/dist/paint-editor/index.cjs +7 -7
  32. package/dist/paint-editor/index.js +2 -2
  33. package/dist/text/layout.d.cts +93 -12
  34. package/dist/text/layout.d.ts +93 -12
  35. package/dist/text/opentype.d.cts +13 -3
  36. package/dist/text/opentype.d.ts +13 -3
  37. package/dist/text/shapers.d.cts +12 -0
  38. package/dist/text/shapers.d.ts +12 -0
  39. package/dist/text/types.d.cts +36 -2
  40. package/dist/text/types.d.ts +36 -2
  41. package/dist/vector/controller.d.cts +8 -0
  42. package/dist/vector/controller.d.ts +8 -0
  43. package/dist/vector/index.cjs +1039 -967
  44. package/dist/vector/index.js +90 -18
  45. package/dist/vector/text.d.cts +5 -3
  46. package/dist/vector/text.d.ts +5 -3
  47. package/dist/vector/textPanel.d.cts +6 -0
  48. package/dist/vector/textPanel.d.ts +6 -0
  49. package/dist/vector/types.d.cts +9 -0
  50. package/dist/vector/types.d.ts +9 -0
  51. package/package.json +1 -1
  52. package/skills/pixerate-image-editor/SKILL.md +4 -2
  53. package/skills/pixerate-image-editor/references/shapes-and-type.md +19 -5
  54. package/skills/pixerate-image-selection-masking/SKILL.md +2 -0
  55. package/skills/pixerate-vector/SKILL.md +9 -3
@@ -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. */
@@ -2,7 +2,7 @@ import { type SelectionMask, type SelectionMode } from './mask.cjs';
2
2
  import type { ColorDistance, ColorRangePreset } from './wand.cjs';
3
3
  import type { RefineEdgeParams } from './refine.cjs';
4
4
  /** Selection tools of the image editor UI. */
5
- export type SelectionToolKind = 'wand' | 'rect' | 'ellipse' | 'row' | 'column' | 'lasso' | 'polygon' | 'range';
5
+ export type SelectionToolKind = 'wand' | 'rect' | 'ellipse' | 'row' | 'column' | 'lasso' | 'polygon' | 'range' | 'type' | 'type-vertical';
6
6
  export declare const SELECTION_TOOLS: readonly {
7
7
  id: SelectionToolKind;
8
8
  label: string;
@@ -31,6 +31,12 @@ export interface SelectionToolOptions {
31
31
  localized?: number;
32
32
  /** Color Range: select everything except the sampled colours. */
33
33
  rangeInvert?: boolean;
34
+ /** Type Mask: the text to select (default "Type"). A click places its first baseline. */
35
+ typeText?: string;
36
+ /** Type Mask: font size in px (default 72). */
37
+ typeSize?: number;
38
+ /** Type Mask: font family (default sans-serif). */
39
+ typeFamily?: string;
34
40
  }
35
41
  export declare const DEFAULT_SELECTION_TOOL_OPTIONS: SelectionToolOptions;
36
42
  /**
@@ -2,7 +2,7 @@ import { type SelectionMask, type SelectionMode } from './mask.js';
2
2
  import type { ColorDistance, ColorRangePreset } from './wand.js';
3
3
  import type { RefineEdgeParams } from './refine.js';
4
4
  /** Selection tools of the image editor UI. */
5
- export type SelectionToolKind = 'wand' | 'rect' | 'ellipse' | 'row' | 'column' | 'lasso' | 'polygon' | 'range';
5
+ export type SelectionToolKind = 'wand' | 'rect' | 'ellipse' | 'row' | 'column' | 'lasso' | 'polygon' | 'range' | 'type' | 'type-vertical';
6
6
  export declare const SELECTION_TOOLS: readonly {
7
7
  id: SelectionToolKind;
8
8
  label: string;
@@ -31,6 +31,12 @@ export interface SelectionToolOptions {
31
31
  localized?: number;
32
32
  /** Color Range: select everything except the sampled colours. */
33
33
  rangeInvert?: boolean;
34
+ /** Type Mask: the text to select (default "Type"). A click places its first baseline. */
35
+ typeText?: string;
36
+ /** Type Mask: font size in px (default 72). */
37
+ typeSize?: number;
38
+ /** Type Mask: font family (default sans-serif). */
39
+ typeFamily?: string;
34
40
  }
35
41
  export declare const DEFAULT_SELECTION_TOOL_OPTIONS: SelectionToolOptions;
36
42
  /**
@@ -48,7 +48,7 @@ export interface ImageEditorToolProviderOptions {
48
48
  * `add_shape_component`, `remove_shape_component`, `merge_shape_components` (see
49
49
  * `createImageShapeTools`); `rasterize_layer` turns one into pixels.
50
50
  * - Type layers: `list_fonts`, `get_text_layer`, `add_text_layer`, `set_text`, `set_text_style`,
51
- * `set_paragraph_style`, `set_text_frame`, `convert_text_to_shape` (see `createImageTypeTools`).
51
+ * `set_paragraph_style`, `set_text_frame`, `set_text_orientation`, `convert_text_to_shape` (see `createImageTypeTools`).
52
52
  * - Colour management: `get_color_profile`, `assign_profile`, `convert_to_profile`,
53
53
  * `set_proof_setup`, `convert_colors` (see `createImageColorTools`).
54
54
  * - Retouching: `clone_stamp`, `heal_brush`, `spot_heal`, `smudge`, `dodge`, `burn`, `sponge`,
@@ -48,7 +48,7 @@ export interface ImageEditorToolProviderOptions {
48
48
  * `add_shape_component`, `remove_shape_component`, `merge_shape_components` (see
49
49
  * `createImageShapeTools`); `rasterize_layer` turns one into pixels.
50
50
  * - Type layers: `list_fonts`, `get_text_layer`, `add_text_layer`, `set_text`, `set_text_style`,
51
- * `set_paragraph_style`, `set_text_frame`, `convert_text_to_shape` (see `createImageTypeTools`).
51
+ * `set_paragraph_style`, `set_text_frame`, `set_text_orientation`, `convert_text_to_shape` (see `createImageTypeTools`).
52
52
  * - Colour management: `get_color_profile`, `assign_profile`, `convert_to_profile`,
53
53
  * `set_proof_setup`, `convert_colors` (see `createImageColorTools`).
54
54
  * - Retouching: `clone_stamp`, `heal_brush`, `spot_heal`, `smudge`, `dodge`, `burn`, `sponge`,
@@ -2,8 +2,8 @@ import type { AgentTool } from '../tools/registry.cjs';
2
2
  import type { ImageEditorController } from './controller.cjs';
3
3
  /**
4
4
  * Agent tools for type layers in the image editor: `list_fonts`, `get_text_layer`,
5
- * `add_text_layer`, `set_text`, `set_text_style`, `set_paragraph_style`, `set_text_frame` and
6
- * `convert_text_to_shape`. Every write is one undo step, validates first and returns the layer as
5
+ * `add_text_layer`, `set_text`, `set_text_style`, `set_paragraph_style`, `set_text_frame`,
6
+ * `set_text_orientation` and `convert_text_to_shape`. Every write is one undo step, validates first and returns the layer as
7
7
  * it is afterwards (with any missing fonts).
8
8
  */
9
9
  export declare function createImageTypeTools(controller: ImageEditorController): AgentTool[];
@@ -2,8 +2,8 @@ import type { AgentTool } from '../tools/registry.js';
2
2
  import type { ImageEditorController } from './controller.js';
3
3
  /**
4
4
  * Agent tools for type layers in the image editor: `list_fonts`, `get_text_layer`,
5
- * `add_text_layer`, `set_text`, `set_text_style`, `set_paragraph_style`, `set_text_frame` and
6
- * `convert_text_to_shape`. Every write is one undo step, validates first and returns the layer as
5
+ * `add_text_layer`, `set_text`, `set_text_style`, `set_paragraph_style`, `set_text_frame`,
6
+ * `set_text_orientation` and `convert_text_to_shape`. Every write is one undo step, validates first and returns the layer as
7
7
  * it is afterwards (with any missing fonts).
8
8
  */
9
9
  export declare function createImageTypeTools(controller: ImageEditorController): AgentTool[];
@@ -7,7 +7,7 @@ var _chunkZ64NRDEHcjs = require('../chunk-Z64NRDEH.cjs');
7
7
 
8
8
 
9
9
 
10
- var _chunk2UR4OX3Bcjs = require('../chunk-2UR4OX3B.cjs');
10
+ var _chunkUYXL6ZWQcjs = require('../chunk-UYXL6ZWQ.cjs');
11
11
  require('../chunk-A2IS7EHE.cjs');
12
12
 
13
13
 
@@ -54,7 +54,7 @@ var _chunkJLWLX52Lcjs = require('../chunk-JLWLX52L.cjs');
54
54
 
55
55
 
56
56
  var _chunkK7ENM55Pcjs = require('../chunk-K7ENM55P.cjs');
57
- require('../chunk-EGZM52EO.cjs');
57
+ require('../chunk-BRKVNXDZ.cjs');
58
58
 
59
59
 
60
60
 
@@ -1653,11 +1653,11 @@ function header(state, options) {
1653
1653
  return out;
1654
1654
  }
1655
1655
  function serializePaintDocument(state, options = {}) {
1656
- const { layers, assets } = _chunk2UR4OX3Bcjs.serializeLayers.call(void 0, state.layers);
1656
+ const { layers, assets } = _chunkUYXL6ZWQcjs.serializeLayers.call(void 0, state.layers);
1657
1657
  return { ...header(state, options), layers, assets };
1658
1658
  }
1659
1659
  async function serializePaintDocumentExternal(state, store, options = {}) {
1660
- const { layers, assets } = await _chunk2UR4OX3Bcjs.serializeLayersExternal.call(void 0, state.layers, store);
1660
+ const { layers, assets } = await _chunkUYXL6ZWQcjs.serializeLayersExternal.call(void 0, state.layers, store);
1661
1661
  return { ...header(state, options), layers, assets };
1662
1662
  }
1663
1663
  function paintLayersOnly(layers, problems) {
@@ -1694,7 +1694,7 @@ function deserializePaintDocument(raw) {
1694
1694
  const canvas = normalizeCanvas({ width: r.width, height: r.height, dpi: _nullishCoalesce(r.dpi, () => ( void 0)) });
1695
1695
  const paper = _chunkYQ5C5BVKcjs.normalizePaper.call(void 0, _nullishCoalesce(r.paper, () => ( {})));
1696
1696
  const assets = r.assets && typeof r.assets === "object" ? r.assets : {};
1697
- const layers = paintLayersOnly(_chunk2UR4OX3Bcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
1697
+ const layers = paintLayersOnly(_chunkUYXL6ZWQcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
1698
1698
  const wanted = typeof r.activeLayerId === "string" ? r.activeLayerId : null;
1699
1699
  const activeLayerId = wanted && _chunkHGTDMKNEcjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkHGTDMKNEcjs.flattenLayers.call(void 0, layers), 'access', _70 => _70.filter, 'call', _71 => _71((l) => l.type === "pixel"), 'access', _72 => _72.pop, 'call', _73 => _73(), 'optionalAccess', _74 => _74.id]), () => ( null));
1700
1700
  const wetEvents = Array.isArray(r.wetEvents) ? r.wetEvents.filter((e) => e && typeof e === "object" && Number.isInteger(e.clock) && typeof e.kind === "string") : [];
@@ -1710,7 +1710,7 @@ async function deserializePaintDocumentAsync(raw, store) {
1710
1710
  if (!raw || typeof raw !== "object") throw new Error("Not a paint document: expected a JSON object.");
1711
1711
  const r = raw;
1712
1712
  const problems = [];
1713
- const assets = await _chunk2UR4OX3Bcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
1713
+ const assets = await _chunkUYXL6ZWQcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
1714
1714
  const loaded = deserializePaintDocument({ ...r, assets });
1715
1715
  return { ...loaded, problems: [...problems, ...loaded.problems] };
1716
1716
  }
@@ -5409,7 +5409,7 @@ var PaintEditorController = (_class10 = class _PaintEditorController {
5409
5409
  return next.type === "group" ? { ...next, children: toStandard(next.children) } : next;
5410
5410
  });
5411
5411
  const layers = toStandard(dried);
5412
- const result = _chunk2UR4OX3Bcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
5412
+ const result = _chunkUYXL6ZWQcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
5413
5413
  for (const [mode, names] of changed) {
5414
5414
  const label = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _271 => _271.find, 'call', _272 => _272((m) => m.id === mode), 'optionalAccess', _273 => _273.label]), () => ( mode));
5415
5415
  const std = _nullishCoalesce(_optionalChain([_chunkCWM3CUUXcjs.BLEND_MODES, 'access', _274 => _274.find, 'call', _275 => _275((m) => m.id === _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _276 => _276.label]), () => ( _chunkCWM3CUUXcjs.standardBlendMode.call(void 0, mode)));
@@ -7,7 +7,7 @@ import {
7
7
  resolveExternalAssets,
8
8
  serializeLayers,
9
9
  serializeLayersExternal
10
- } from "../chunk-TXYXF32N.js";
10
+ } from "../chunk-ZIDUPSP4.js";
11
11
  import "../chunk-3CI7FRMK.js";
12
12
  import {
13
13
  EffectRendererPool
@@ -54,7 +54,7 @@ import {
54
54
  realPresenceClock,
55
55
  tweenPresenceCursor
56
56
  } from "../chunk-IVSWRVB4.js";
57
- import "../chunk-LPIKXPBM.js";
57
+ import "../chunk-GHCXLQ47.js";
58
58
  import {
59
59
  BRUSH_ID,
60
60
  BRUSH_ROTATIONS,
@@ -2,11 +2,11 @@
2
2
  * Text layout shared by the image editor's type layers and the vector editor's text nodes: styled
3
3
  * runs, paragraphs, line breaking (at spaces and after break characters, and between wide CJK
4
4
  * characters), alignment and justification, tracking, leading, indents, spacing, baseline shift,
5
- * caret positions and hit testing. Everything that needs a font goes through a `TextShaper`, so
5
+ * horizontal and vertical writing, caret positions and hit testing. Everything that needs a font goes through a `TextShaper`, so
6
6
  * the same measurements give the same lines in every host.
7
7
  */
8
8
  import type { BezierPath } from '../canvas/pathops/bezier.cjs';
9
- import type { ParagraphRun, TextFont, TextRect, TextShaper, TextStyle } from './types.cjs';
9
+ import type { ParagraphRun, TextFont, TextOrientation, TextRect, TextShaper, TextStyle } from './types.cjs';
10
10
  /** What layout needs: the text, its character and paragraph runs and its frame. */
11
11
  export interface TextBlock {
12
12
  text: string;
@@ -28,6 +28,12 @@ export interface TextBlock {
28
28
  width: number;
29
29
  height: number;
30
30
  };
31
+ /**
32
+ * Default `horizontal`. `vertical`: lines are columns running down, stacked right to left. Point
33
+ * text then starts at (0, 0) at the top of the first column's centre line (`origin: 'top'`: its
34
+ * right edge); a box's columns start at its right edge and wrap at its height.
35
+ */
36
+ orientation?: TextOrientation;
31
37
  }
32
38
  export declare const DEFAULT_TEXT_STYLE: TextStyle;
33
39
  export declare const DEFAULT_AUTO_LEADING = 1.2;
@@ -65,14 +71,39 @@ export declare function paragraphRanges(text: string): Array<{
65
71
  }>;
66
72
  /** Paragraph runs snapped to whole paragraphs: each paragraph takes the style at its start. */
67
73
  export declare function fitParagraphRuns(runs: readonly ParagraphRun[], text: string): ParagraphRun[];
74
+ /** A point in text space (or line space, where said). */
75
+ export interface TextPoint {
76
+ x: number;
77
+ y: number;
78
+ }
79
+ /** An affine matrix `[a, b, c, d, e, f]`: `x' = a·x + c·y + e`, `y' = b·x + d·y + f`. */
80
+ export type TextMatrix = readonly [number, number, number, number, number, number];
68
81
  /** One laid-out character. */
69
82
  export interface LaidChar {
70
83
  /** Index in the text (UTF-16 code unit). */
71
84
  index: number;
72
- /** Text-space x of its start and its advance (tracking and justification included). */
85
+ /** Line-space x of its start and its advance (tracking and justification included). */
73
86
  x: number;
74
87
  advance: number;
75
88
  }
89
+ /**
90
+ * A character of vertical text as drawn, text space: its origin on its own baseline, its turn
91
+ * (`90`: turned sideways, clockwise; `0`: upright), its advance along its baseline and its box
92
+ * above and below the baseline.
93
+ */
94
+ export interface LaidGlyph {
95
+ index: number;
96
+ /** Code units (2 for a surrogate pair). */
97
+ length: number;
98
+ x: number;
99
+ y: number;
100
+ angle: 0 | 90;
101
+ advance: number;
102
+ ascent: number;
103
+ descent: number;
104
+ /** Drawn with the font's vertical alternate (`vert`). */
105
+ vert: boolean;
106
+ }
76
107
  /** A run of characters on one line in one style. */
77
108
  export interface LaidFragment {
78
109
  start: number;
@@ -81,18 +112,24 @@ export interface LaidFragment {
81
112
  font: TextFont;
82
113
  /** The family the shaper draws it with. */
83
114
  family: string;
115
+ /** Line space. */
84
116
  x: number;
85
- /** Baseline in text space (baseline shift applied). */
117
+ /** Baseline in line space (baseline shift applied); for upright vertical text, the column's centre line. */
86
118
  y: number;
87
119
  /** Per-character x positions relative to `x` (`end − start + 1` entries). */
88
120
  carets: number[];
89
121
  /** Whether characters are placed one by one (tracking or justification). */
90
122
  spaced: boolean;
123
+ /** Vertical text only: whether the fragment's characters stand upright (else they are turned sideways). */
124
+ upright?: boolean;
125
+ /** Vertical text only: each character as drawn, text space (low surrogates join their pair). */
126
+ glyphs?: LaidGlyph[];
91
127
  }
92
128
  export interface LaidLine {
93
129
  start: number;
94
130
  /** End of the line's characters (line break and trailing spaces excluded from `width`). */
95
131
  end: number;
132
+ /** Line space; for vertical text the column's centre line. */
96
133
  baseline: number;
97
134
  ascent: number;
98
135
  descent: number;
@@ -100,34 +137,78 @@ export interface LaidLine {
100
137
  width: number;
101
138
  chars: LaidChar[];
102
139
  fragments: LaidFragment[];
140
+ /** Vertical text only: line space → text space (the layout's `matrix`). */
141
+ matrix?: TextMatrix;
103
142
  }
104
- /** A laid-out type layer in text space. */
143
+ /** A laid-out type layer. */
105
144
  export interface TextLayout {
106
145
  lines: LaidLine[];
107
146
  /** Bounds of the lines (ascent to descent), text space; the box for paragraph text. */
108
147
  bounds: TextRect;
109
148
  /** Families replaced by a fallback. */
110
149
  missingFonts: string[];
150
+ orientation: TextOrientation;
151
+ /** Vertical text only: line space → text space. */
152
+ matrix?: TextMatrix;
111
153
  }
112
154
  export declare function fontOf(style: TextStyle): TextFont;
113
155
  /** Whether a character is a space or tab (spaces hang at line ends and stretch when justifying). */
114
156
  export declare const isTextSpace: (c: string) => c is "\t" | " ";
157
+ /**
158
+ * How a code point is set in vertical text, after Unicode's Vertical_Orientation (UAX #50),
159
+ * simplified to CJK: `U` upright (ideographs, kana, Hangul, full-width forms, emoji), `R` turned
160
+ * sideways (Latin and other horizontal scripts, spaces), `Tu` upright in a vertical form when the
161
+ * font has one (、。 and small kana), `Tr` a vertical form when the font has one, else turned
162
+ * sideways (brackets, dashes, the long vowel mark, wave dash).
163
+ */
164
+ export declare function verticalOrientationOf(cp: number): 'U' | 'R' | 'Tu' | 'Tr';
165
+ /** A rectangle mapped through `m` (a quarter turn keeps it a rectangle); `r` itself without `m`. */
166
+ export declare function transformTextRect(m: TextMatrix | undefined, r: TextRect): TextRect;
167
+ /** A line-space point of `layout` in text space (the same point for horizontal text). */
168
+ export declare function lineToTextSpace(layout: Pick<TextLayout, 'matrix'>, p: TextPoint): TextPoint;
169
+ /** A text-space point of `layout` in line space (the same point for horizontal text). */
170
+ export declare function textToLineSpace(layout: Pick<TextLayout, 'matrix'>, p: TextPoint): TextPoint;
171
+ /** A line's box (its advance by ascent to descent) in text space. */
172
+ export declare function textLineRect(l: LaidLine): TextRect;
115
173
  /** Lays out a type layer with `shaper` (memoised per layer object and shaper). */
116
174
  export declare function layoutText(layer: TextBlock, shaper: TextShaper): TextLayout;
117
175
  /** The text index nearest a text-space point (for clicks): the line under it, then the closest caret. */
118
- export declare function textIndexAt(layout: TextLayout, p: {
119
- x: number;
120
- y: number;
121
- }): number;
122
- /** The caret at text index `index`: its x and the line's top and bottom, text space. */
176
+ export declare function textIndexAt(layout: TextLayout, point: TextPoint): number;
177
+ /**
178
+ * The caret at text index `index`: in line space its x and the line's top and bottom, and in text
179
+ * space the segment it draws (`from` the line's top or, vertically, its right edge, `to` the other
180
+ * side).
181
+ */
123
182
  export declare function caretAt(layout: TextLayout, index: number): {
124
183
  x: number;
125
184
  top: number;
126
185
  bottom: number;
127
186
  line: number;
187
+ from: TextPoint;
188
+ to: TextPoint;
128
189
  };
129
- /** Underline and strike-through bars of a fragment, text space, as rectangles. */
190
+ /** Quads (text space, four corners each) covering the characters of [start, end), one per line. */
191
+ export declare function textSelectionQuads(layout: TextLayout, start: number, end: number): TextPoint[][];
192
+ /** What an arrow key does to a text caret: along the line (`previous` / `next` character) or across lines. */
193
+ export type TextCaretStep = 'previous' | 'next' | 'line-before' | 'line-after';
194
+ /**
195
+ * The caret step of an arrow key. Horizontal text: ← → move along the line, ↑ ↓ between lines.
196
+ * Vertical text: ↑ ↓ move along the column, → to the column before (on the right), ← to the next.
197
+ */
198
+ export declare function textArrowStep(orientation: TextOrientation | undefined, key: 'ArrowLeft' | 'ArrowRight' | 'ArrowUp' | 'ArrowDown'): TextCaretStep;
199
+ /**
200
+ * The index on the line before (`dir` −1) or after (+1) the caret at `index`, at the same place
201
+ * along the line; the start or end of the text (`length`) past the first or last line.
202
+ */
203
+ export declare function textLineMove(layout: TextLayout, index: number, dir: -1 | 1, length: number): number;
204
+ /** Underline and strike-through bars of a fragment, text space, as rectangles. Vertical text underlines on the right. */
130
205
  export declare function textDecorations(f: LaidFragment, l: LaidLine): TextRect[];
131
206
  export declare const textRectPath: (r: TextRect) => BezierPath;
132
- /** The text of a fragment as outlines (one placement per character when spaced), text space. */
207
+ /** The text of a fragment as outlines (one placement per character when spaced or vertical), text space. */
133
208
  export declare function textFragmentOutline(shaper: TextShaper, text: string, f: LaidFragment): BezierPath;
209
+ /**
210
+ * Draws a fragment's text with a drawing shaper in the context's current transform (text space),
211
+ * fill style and alpha: each glyph of vertical text turned or upright, spaced text a character at
212
+ * a time. Decorations are not drawn (see `textDecorations`).
213
+ */
214
+ export declare function drawTextFragment(ctx: CanvasRenderingContext2D, shaper: TextShaper, text: string, f: LaidFragment): void;
@@ -2,11 +2,11 @@
2
2
  * Text layout shared by the image editor's type layers and the vector editor's text nodes: styled
3
3
  * runs, paragraphs, line breaking (at spaces and after break characters, and between wide CJK
4
4
  * characters), alignment and justification, tracking, leading, indents, spacing, baseline shift,
5
- * caret positions and hit testing. Everything that needs a font goes through a `TextShaper`, so
5
+ * horizontal and vertical writing, caret positions and hit testing. Everything that needs a font goes through a `TextShaper`, so
6
6
  * the same measurements give the same lines in every host.
7
7
  */
8
8
  import type { BezierPath } from '../canvas/pathops/bezier.js';
9
- import type { ParagraphRun, TextFont, TextRect, TextShaper, TextStyle } from './types.js';
9
+ import type { ParagraphRun, TextFont, TextOrientation, TextRect, TextShaper, TextStyle } from './types.js';
10
10
  /** What layout needs: the text, its character and paragraph runs and its frame. */
11
11
  export interface TextBlock {
12
12
  text: string;
@@ -28,6 +28,12 @@ export interface TextBlock {
28
28
  width: number;
29
29
  height: number;
30
30
  };
31
+ /**
32
+ * Default `horizontal`. `vertical`: lines are columns running down, stacked right to left. Point
33
+ * text then starts at (0, 0) at the top of the first column's centre line (`origin: 'top'`: its
34
+ * right edge); a box's columns start at its right edge and wrap at its height.
35
+ */
36
+ orientation?: TextOrientation;
31
37
  }
32
38
  export declare const DEFAULT_TEXT_STYLE: TextStyle;
33
39
  export declare const DEFAULT_AUTO_LEADING = 1.2;
@@ -65,14 +71,39 @@ export declare function paragraphRanges(text: string): Array<{
65
71
  }>;
66
72
  /** Paragraph runs snapped to whole paragraphs: each paragraph takes the style at its start. */
67
73
  export declare function fitParagraphRuns(runs: readonly ParagraphRun[], text: string): ParagraphRun[];
74
+ /** A point in text space (or line space, where said). */
75
+ export interface TextPoint {
76
+ x: number;
77
+ y: number;
78
+ }
79
+ /** An affine matrix `[a, b, c, d, e, f]`: `x' = a·x + c·y + e`, `y' = b·x + d·y + f`. */
80
+ export type TextMatrix = readonly [number, number, number, number, number, number];
68
81
  /** One laid-out character. */
69
82
  export interface LaidChar {
70
83
  /** Index in the text (UTF-16 code unit). */
71
84
  index: number;
72
- /** Text-space x of its start and its advance (tracking and justification included). */
85
+ /** Line-space x of its start and its advance (tracking and justification included). */
73
86
  x: number;
74
87
  advance: number;
75
88
  }
89
+ /**
90
+ * A character of vertical text as drawn, text space: its origin on its own baseline, its turn
91
+ * (`90`: turned sideways, clockwise; `0`: upright), its advance along its baseline and its box
92
+ * above and below the baseline.
93
+ */
94
+ export interface LaidGlyph {
95
+ index: number;
96
+ /** Code units (2 for a surrogate pair). */
97
+ length: number;
98
+ x: number;
99
+ y: number;
100
+ angle: 0 | 90;
101
+ advance: number;
102
+ ascent: number;
103
+ descent: number;
104
+ /** Drawn with the font's vertical alternate (`vert`). */
105
+ vert: boolean;
106
+ }
76
107
  /** A run of characters on one line in one style. */
77
108
  export interface LaidFragment {
78
109
  start: number;
@@ -81,18 +112,24 @@ export interface LaidFragment {
81
112
  font: TextFont;
82
113
  /** The family the shaper draws it with. */
83
114
  family: string;
115
+ /** Line space. */
84
116
  x: number;
85
- /** Baseline in text space (baseline shift applied). */
117
+ /** Baseline in line space (baseline shift applied); for upright vertical text, the column's centre line. */
86
118
  y: number;
87
119
  /** Per-character x positions relative to `x` (`end − start + 1` entries). */
88
120
  carets: number[];
89
121
  /** Whether characters are placed one by one (tracking or justification). */
90
122
  spaced: boolean;
123
+ /** Vertical text only: whether the fragment's characters stand upright (else they are turned sideways). */
124
+ upright?: boolean;
125
+ /** Vertical text only: each character as drawn, text space (low surrogates join their pair). */
126
+ glyphs?: LaidGlyph[];
91
127
  }
92
128
  export interface LaidLine {
93
129
  start: number;
94
130
  /** End of the line's characters (line break and trailing spaces excluded from `width`). */
95
131
  end: number;
132
+ /** Line space; for vertical text the column's centre line. */
96
133
  baseline: number;
97
134
  ascent: number;
98
135
  descent: number;
@@ -100,34 +137,78 @@ export interface LaidLine {
100
137
  width: number;
101
138
  chars: LaidChar[];
102
139
  fragments: LaidFragment[];
140
+ /** Vertical text only: line space → text space (the layout's `matrix`). */
141
+ matrix?: TextMatrix;
103
142
  }
104
- /** A laid-out type layer in text space. */
143
+ /** A laid-out type layer. */
105
144
  export interface TextLayout {
106
145
  lines: LaidLine[];
107
146
  /** Bounds of the lines (ascent to descent), text space; the box for paragraph text. */
108
147
  bounds: TextRect;
109
148
  /** Families replaced by a fallback. */
110
149
  missingFonts: string[];
150
+ orientation: TextOrientation;
151
+ /** Vertical text only: line space → text space. */
152
+ matrix?: TextMatrix;
111
153
  }
112
154
  export declare function fontOf(style: TextStyle): TextFont;
113
155
  /** Whether a character is a space or tab (spaces hang at line ends and stretch when justifying). */
114
156
  export declare const isTextSpace: (c: string) => c is "\t" | " ";
157
+ /**
158
+ * How a code point is set in vertical text, after Unicode's Vertical_Orientation (UAX #50),
159
+ * simplified to CJK: `U` upright (ideographs, kana, Hangul, full-width forms, emoji), `R` turned
160
+ * sideways (Latin and other horizontal scripts, spaces), `Tu` upright in a vertical form when the
161
+ * font has one (、。 and small kana), `Tr` a vertical form when the font has one, else turned
162
+ * sideways (brackets, dashes, the long vowel mark, wave dash).
163
+ */
164
+ export declare function verticalOrientationOf(cp: number): 'U' | 'R' | 'Tu' | 'Tr';
165
+ /** A rectangle mapped through `m` (a quarter turn keeps it a rectangle); `r` itself without `m`. */
166
+ export declare function transformTextRect(m: TextMatrix | undefined, r: TextRect): TextRect;
167
+ /** A line-space point of `layout` in text space (the same point for horizontal text). */
168
+ export declare function lineToTextSpace(layout: Pick<TextLayout, 'matrix'>, p: TextPoint): TextPoint;
169
+ /** A text-space point of `layout` in line space (the same point for horizontal text). */
170
+ export declare function textToLineSpace(layout: Pick<TextLayout, 'matrix'>, p: TextPoint): TextPoint;
171
+ /** A line's box (its advance by ascent to descent) in text space. */
172
+ export declare function textLineRect(l: LaidLine): TextRect;
115
173
  /** Lays out a type layer with `shaper` (memoised per layer object and shaper). */
116
174
  export declare function layoutText(layer: TextBlock, shaper: TextShaper): TextLayout;
117
175
  /** The text index nearest a text-space point (for clicks): the line under it, then the closest caret. */
118
- export declare function textIndexAt(layout: TextLayout, p: {
119
- x: number;
120
- y: number;
121
- }): number;
122
- /** The caret at text index `index`: its x and the line's top and bottom, text space. */
176
+ export declare function textIndexAt(layout: TextLayout, point: TextPoint): number;
177
+ /**
178
+ * The caret at text index `index`: in line space its x and the line's top and bottom, and in text
179
+ * space the segment it draws (`from` the line's top or, vertically, its right edge, `to` the other
180
+ * side).
181
+ */
123
182
  export declare function caretAt(layout: TextLayout, index: number): {
124
183
  x: number;
125
184
  top: number;
126
185
  bottom: number;
127
186
  line: number;
187
+ from: TextPoint;
188
+ to: TextPoint;
128
189
  };
129
- /** Underline and strike-through bars of a fragment, text space, as rectangles. */
190
+ /** Quads (text space, four corners each) covering the characters of [start, end), one per line. */
191
+ export declare function textSelectionQuads(layout: TextLayout, start: number, end: number): TextPoint[][];
192
+ /** What an arrow key does to a text caret: along the line (`previous` / `next` character) or across lines. */
193
+ export type TextCaretStep = 'previous' | 'next' | 'line-before' | 'line-after';
194
+ /**
195
+ * The caret step of an arrow key. Horizontal text: ← → move along the line, ↑ ↓ between lines.
196
+ * Vertical text: ↑ ↓ move along the column, → to the column before (on the right), ← to the next.
197
+ */
198
+ export declare function textArrowStep(orientation: TextOrientation | undefined, key: 'ArrowLeft' | 'ArrowRight' | 'ArrowUp' | 'ArrowDown'): TextCaretStep;
199
+ /**
200
+ * The index on the line before (`dir` −1) or after (+1) the caret at `index`, at the same place
201
+ * along the line; the start or end of the text (`length`) past the first or last line.
202
+ */
203
+ export declare function textLineMove(layout: TextLayout, index: number, dir: -1 | 1, length: number): number;
204
+ /** Underline and strike-through bars of a fragment, text space, as rectangles. Vertical text underlines on the right. */
130
205
  export declare function textDecorations(f: LaidFragment, l: LaidLine): TextRect[];
131
206
  export declare const textRectPath: (r: TextRect) => BezierPath;
132
- /** The text of a fragment as outlines (one placement per character when spaced), text space. */
207
+ /** The text of a fragment as outlines (one placement per character when spaced or vertical), text space. */
133
208
  export declare function textFragmentOutline(shaper: TextShaper, text: string, f: LaidFragment): BezierPath;
209
+ /**
210
+ * Draws a fragment's text with a drawing shaper in the context's current transform (text space),
211
+ * fill style and alpha: each glyph of vertical text turned or upright, spaced text a character at
212
+ * a time. Decorations are not drawn (see `textDecorations`).
213
+ */
214
+ export declare function drawTextFragment(ctx: CanvasRenderingContext2D, shaper: TextShaper, text: string, f: LaidFragment): void;