@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.
- package/dist/animation-editor/index.cjs +56 -56
- package/dist/animation-editor/index.js +2 -2
- package/dist/{chunk-ZQGZWFPU.cjs → chunk-3T5VCDIV.cjs} +97 -5
- package/dist/{chunk-RQ2EM5TY.js → chunk-5OC22IEO.js} +97 -5
- package/dist/{chunk-EGZM52EO.cjs → chunk-BRKVNXDZ.cjs} +354 -125
- package/dist/{chunk-XCDGM7TD.cjs → chunk-FR2Q2LVF.cjs} +35 -35
- package/dist/{chunk-LPIKXPBM.js → chunk-GHCXLQ47.js} +262 -33
- package/dist/{chunk-VRXXAXUT.js → chunk-MLC7HUHO.js} +1 -1
- package/dist/{chunk-2UR4OX3B.cjs → chunk-UYXL6ZWQ.cjs} +114 -97
- package/dist/{chunk-TXYXF32N.js → chunk-ZIDUPSP4.js} +35 -18
- package/dist/image-editor/controller.d.cts +31 -2
- package/dist/image-editor/controller.d.ts +31 -2
- package/dist/image-editor/index.cjs +1064 -923
- package/dist/image-editor/index.js +204 -63
- package/dist/image-editor/layers/model.d.cts +7 -2
- package/dist/image-editor/layers/model.d.ts +7 -2
- package/dist/image-editor/layers/serialize.d.cts +2 -0
- package/dist/image-editor/layers/serialize.d.ts +2 -0
- package/dist/image-editor/layers/shape-type-ui.d.cts +8 -2
- package/dist/image-editor/layers/shape-type-ui.d.ts +8 -2
- package/dist/image-editor/layers/text.d.cts +6 -2
- package/dist/image-editor/layers/text.d.ts +6 -2
- package/dist/image-editor/psd/type.d.cts +2 -1
- package/dist/image-editor/psd/type.d.ts +2 -1
- package/dist/image-editor/selection/tool-options.d.cts +7 -1
- package/dist/image-editor/selection/tool-options.d.ts +7 -1
- package/dist/image-editor/tools.d.cts +1 -1
- package/dist/image-editor/tools.d.ts +1 -1
- package/dist/image-editor/type-tools.d.cts +2 -2
- package/dist/image-editor/type-tools.d.ts +2 -2
- package/dist/paint-editor/index.cjs +7 -7
- package/dist/paint-editor/index.js +2 -2
- package/dist/text/layout.d.cts +93 -12
- package/dist/text/layout.d.ts +93 -12
- package/dist/text/opentype.d.cts +13 -3
- package/dist/text/opentype.d.ts +13 -3
- package/dist/text/shapers.d.cts +12 -0
- package/dist/text/shapers.d.ts +12 -0
- package/dist/text/types.d.cts +36 -2
- package/dist/text/types.d.ts +36 -2
- package/dist/vector/controller.d.cts +8 -0
- package/dist/vector/controller.d.ts +8 -0
- package/dist/vector/index.cjs +1039 -967
- package/dist/vector/index.js +90 -18
- package/dist/vector/text.d.cts +5 -3
- package/dist/vector/text.d.ts +5 -3
- package/dist/vector/textPanel.d.cts +6 -0
- package/dist/vector/textPanel.d.ts +6 -0
- package/dist/vector/types.d.cts +9 -0
- package/dist/vector/types.d.ts +9 -0
- package/package.json +1 -1
- package/skills/pixerate-image-editor/SKILL.md +4 -2
- package/skills/pixerate-image-editor/references/shapes-and-type.md +19 -5
- package/skills/pixerate-image-selection-masking/SKILL.md +2 -0
- 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-
|
|
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-
|
|
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-
|
|
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
|
-
/**
|
|
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
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
this.move(mod2 ? "
|
|
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.
|
|
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),
|
|
@@ -9346,6 +9338,55 @@ var ImageEditorController = class {
|
|
|
9346
9338
|
* text wrapped in `box`. Refused without a text shaper. Returns its id.
|
|
9347
9339
|
*/
|
|
9348
9340
|
addTextLayer(init) {
|
|
9341
|
+
const layer = this.layoutTypeLayer(init);
|
|
9342
|
+
if (init.opacity !== void 0 && !(Number.isFinite(init.opacity) && init.opacity >= 0 && init.opacity <= 1)) throw new LayerOperationError("opacity must be between 0 and 1.");
|
|
9343
|
+
if (init.blend !== void 0 && !isBlendMode(init.blend)) throw new LayerOperationError(`Unknown blend mode "${String(init.blend)}".`);
|
|
9344
|
+
if (init.opacity !== void 0) layer.opacity = init.opacity;
|
|
9345
|
+
if (init.blend !== void 0) layer.blend = init.blend;
|
|
9346
|
+
const next = placeLayer(this.state.layers, layer, this.newLayerPlacement(init));
|
|
9347
|
+
this.commitLayers(next, () => {
|
|
9348
|
+
this.state.activeLayerId = layer.id;
|
|
9349
|
+
this.state.activeTarget = "pixels";
|
|
9350
|
+
});
|
|
9351
|
+
return layer.id;
|
|
9352
|
+
}
|
|
9353
|
+
/**
|
|
9354
|
+
* Type Mask (horizontal or vertical): a selection in the shape of `text`, laid out and drawn as
|
|
9355
|
+
* `addTextLayer` would place it (font, size, tracking, box, rotation), combined with the current
|
|
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.
|
|
9358
|
+
*/
|
|
9359
|
+
selectTextShape(init) {
|
|
9360
|
+
const vertical = init.orientation === "vertical";
|
|
9361
|
+
if (init.orientation !== void 0 && init.orientation !== "horizontal" && !vertical) throw new LayerOperationError("orientation must be horizontal or vertical.");
|
|
9362
|
+
if (init.feather !== void 0 && !(init.feather >= 0 && init.feather <= 1e3)) throw new LayerOperationError("feather must be from 0 to 1000 px.");
|
|
9363
|
+
const text = normalizeText(init.text);
|
|
9364
|
+
if (!text.trim()) throw new LayerOperationError("The text is empty, so there is nothing to select; give some characters.");
|
|
9365
|
+
const layer = this.layoutTypeLayer({ ...init, text, orientation: vertical ? "vertical" : "horizontal" });
|
|
9366
|
+
const { width, height } = this.naturalSize;
|
|
9367
|
+
const b = contentBounds(layer.surface);
|
|
9368
|
+
const x0 = Math.max(0, b?.x ?? 0);
|
|
9369
|
+
const y0 = Math.max(0, b?.y ?? 0);
|
|
9370
|
+
const x1 = Math.min(width, b ? b.x + b.width : 0);
|
|
9371
|
+
const y1 = Math.min(height, b ? b.y + b.height : 0);
|
|
9372
|
+
let mask;
|
|
9373
|
+
if (!b || x1 <= x0 || y1 <= y0) mask = createSelectionMask(width, height);
|
|
9374
|
+
else {
|
|
9375
|
+
const rect = { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
|
|
9376
|
+
const rgba = readRegion(layer.surface, rect);
|
|
9377
|
+
const bytes = new Uint8Array(rect.width * rect.height);
|
|
9378
|
+
const hard = init.antiAlias === false;
|
|
9379
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
9380
|
+
const a = rgba[i * 4 + 3];
|
|
9381
|
+
bytes[i] = hard ? a >= 128 ? 255 : 0 : a;
|
|
9382
|
+
}
|
|
9383
|
+
mask = selectionFromRegion(width, height, rect, bytes);
|
|
9384
|
+
}
|
|
9385
|
+
if ((init.feather ?? 0) > 0 && mask.bounds) mask = modifySelection(mask, "feather", init.feather);
|
|
9386
|
+
return this.setSelection(mask.bounds ? mask : null, init.mode ?? "replace");
|
|
9387
|
+
}
|
|
9388
|
+
/** A type layer laid out and drawn from `init` (not added): the shared part of `addTextLayer` and the type masks. */
|
|
9389
|
+
layoutTypeLayer(init) {
|
|
9349
9390
|
const text = normalizeText(init.text);
|
|
9350
9391
|
if (!Number.isFinite(init.x) || !Number.isFinite(init.y)) throw new LayerOperationError("x and y must be numbers (document pixels).");
|
|
9351
9392
|
const style = patchTextStyle({ ...DEFAULT_TEXT_STYLE, color: this.state.paint.foreground }, init.style ?? {});
|
|
@@ -9356,20 +9397,11 @@ var ImageEditorController = class {
|
|
|
9356
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.");
|
|
9357
9398
|
frame = { kind: "box", width, height };
|
|
9358
9399
|
}
|
|
9400
|
+
const orientation = init.orientation === void 0 ? "horizontal" : textOrientation(init.orientation);
|
|
9359
9401
|
if (init.rotation !== void 0 && !Number.isFinite(init.rotation)) throw new LayerOperationError("rotation must be a number of degrees.");
|
|
9360
|
-
if (init.opacity !== void 0 && !(Number.isFinite(init.opacity) && init.opacity >= 0 && init.opacity <= 1)) throw new LayerOperationError("opacity must be between 0 and 1.");
|
|
9361
|
-
if (init.blend !== void 0 && !isBlendMode(init.blend)) throw new LayerOperationError(`Unknown blend mode "${String(init.blend)}".`);
|
|
9362
9402
|
const t = [1, 0, 0, 1, init.x, init.y];
|
|
9363
9403
|
const transform = init.rotation ? multiplyMatrices(t, rotateMatrix(init.rotation, { x: init.x, y: init.y })) : t;
|
|
9364
|
-
|
|
9365
|
-
if (init.opacity !== void 0) layer.opacity = init.opacity;
|
|
9366
|
-
if (init.blend !== void 0) layer.blend = init.blend;
|
|
9367
|
-
const next = placeLayer(this.state.layers, layer, this.newLayerPlacement(init));
|
|
9368
|
-
this.commitLayers(next, () => {
|
|
9369
|
-
this.state.activeLayerId = layer.id;
|
|
9370
|
-
this.state.activeTarget = "pixels";
|
|
9371
|
-
});
|
|
9372
|
-
return layer.id;
|
|
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());
|
|
9373
9405
|
}
|
|
9374
9406
|
/**
|
|
9375
9407
|
* Replaces text [start, end) (default all of it) with `text`; inserted text takes the style at
|
|
@@ -9444,14 +9476,27 @@ var ImageEditorController = class {
|
|
|
9444
9476
|
this.state.layers,
|
|
9445
9477
|
id,
|
|
9446
9478
|
(l) => {
|
|
9447
|
-
if (frame.kind === "box" && l.frame.kind === "box") return { frame: { kind: "box", width: frame.width, height: frame.height } };
|
|
9448
|
-
if (!shaper) throw new LayerOperationError("Changing between point and paragraph text needs a text shaper to measure the text.");
|
|
9449
|
-
const lines = layoutText(l, shaper).lines;
|
|
9450
|
-
const first = lines[0];
|
|
9451
|
-
const dx = frame.kind === "box" ? first ? first.x : 0 : 0;
|
|
9452
|
-
const dy = frame.kind === "box" ? first ? first.baseline - first.ascent : 0 : first ? first.baseline : 0;
|
|
9453
9479
|
const m = textMatrix(l);
|
|
9454
|
-
const
|
|
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);
|
|
9455
9500
|
const nextFrame = frame.kind === "box" ? { kind: "box", width: frame.width, height: frame.height } : { kind: "point" };
|
|
9456
9501
|
return { frame: nextFrame, transform: shifted };
|
|
9457
9502
|
},
|
|
@@ -9461,6 +9506,25 @@ var ImageEditorController = class {
|
|
|
9461
9506
|
this.commitLayers(layers, void 0, commitToHistory);
|
|
9462
9507
|
return this.typeInfo(id);
|
|
9463
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
|
+
}
|
|
9464
9528
|
/**
|
|
9465
9529
|
* Convert to Shape: the text's glyph outlines become a shape layer with the same id, name and
|
|
9466
9530
|
* layer properties (needs a shaper that gives outlines). The fill is the first run's colour;
|
|
@@ -9506,8 +9570,8 @@ var ImageEditorController = class {
|
|
|
9506
9570
|
if (!layout) return null;
|
|
9507
9571
|
const c = caretAt(layout, Math.max(0, Math.min(layer.text.length, index)));
|
|
9508
9572
|
const m = textMatrix(layer);
|
|
9509
|
-
const at = (
|
|
9510
|
-
return { top: at(c.
|
|
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 };
|
|
9511
9575
|
}
|
|
9512
9576
|
// --- Shape layers ---
|
|
9513
9577
|
/** What shape rendering needs: the canvas size and the document's patterns. */
|
|
@@ -11255,8 +11319,8 @@ var DEPTH_MASK_CONTROLS = [
|
|
|
11255
11319
|
// src/image-editor/playback.ts
|
|
11256
11320
|
var IMAGE_PLAYBACK_KIND = "layer";
|
|
11257
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)$/;
|
|
11258
|
-
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)$/;
|
|
11259
|
-
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)$/;
|
|
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)$/;
|
|
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)$/;
|
|
11260
11324
|
var CROP = /^(set_crop|crop_to_selection|reset_crop|set_rotation|flip_image|transform_layer|warp_layer|flip_layer|offset_layer)$/;
|
|
11261
11325
|
var ADJUST = /^(set_adjustments|add_adjustment_layer|update_adjustment_layer|remove_adjustment_layer|move_adjustment_layer)$/;
|
|
11262
11326
|
function imagePlaybackPanel(tool) {
|
|
@@ -11376,7 +11440,9 @@ var SELECTION_TOOLS = [
|
|
|
11376
11440
|
{ id: "column", label: "Single Column" },
|
|
11377
11441
|
{ id: "lasso", label: "Lasso" },
|
|
11378
11442
|
{ id: "polygon", label: "Polygonal Lasso" },
|
|
11379
|
-
{ id: "range", label: "Color Range" }
|
|
11443
|
+
{ id: "range", label: "Color Range" },
|
|
11444
|
+
{ id: "type", label: "Type Mask" },
|
|
11445
|
+
{ id: "type-vertical", label: "Vertical Type Mask" }
|
|
11380
11446
|
];
|
|
11381
11447
|
var COLOR_RANGE_PRESET_LABELS = {
|
|
11382
11448
|
reds: "Reds",
|
|
@@ -11407,7 +11473,10 @@ var DEFAULT_SELECTION_TOOL_OPTIONS = {
|
|
|
11407
11473
|
feather: 0,
|
|
11408
11474
|
fuzziness: 40,
|
|
11409
11475
|
localized: 0,
|
|
11410
|
-
rangeInvert: false
|
|
11476
|
+
rangeInvert: false,
|
|
11477
|
+
typeText: "Type",
|
|
11478
|
+
typeSize: 72,
|
|
11479
|
+
typeFamily: "sans-serif"
|
|
11411
11480
|
};
|
|
11412
11481
|
function selectionModeFromModifiers(modifiers, fallback) {
|
|
11413
11482
|
if (modifiers.shiftKey && modifiers.altKey) return "intersect";
|
|
@@ -12852,6 +12921,7 @@ function describeLayer(layer, activeId, boundsOf) {
|
|
|
12852
12921
|
out.text = {
|
|
12853
12922
|
text: layer.text.length > 80 ? `${layer.text.slice(0, 80)}\u2026` : layer.text,
|
|
12854
12923
|
frame: layer.frame.kind,
|
|
12924
|
+
...layer.orientation === "vertical" ? { orientation: "vertical" } : {},
|
|
12855
12925
|
runs: layer.runs.length,
|
|
12856
12926
|
rendering: layer.rendering === "stored" ? "stored" : "live",
|
|
12857
12927
|
missingFonts: layer.missingFonts ?? []
|
|
@@ -13789,6 +13859,24 @@ var SelectionGesture = class {
|
|
|
13789
13859
|
}
|
|
13790
13860
|
return;
|
|
13791
13861
|
}
|
|
13862
|
+
if (options.tool === "type" || options.tool === "type-vertical") {
|
|
13863
|
+
this.start = null;
|
|
13864
|
+
try {
|
|
13865
|
+
this.controller.selectTextShape({
|
|
13866
|
+
text: options.typeText || "Type",
|
|
13867
|
+
x: point.x,
|
|
13868
|
+
y: point.y,
|
|
13869
|
+
orientation: options.tool === "type-vertical" ? "vertical" : "horizontal",
|
|
13870
|
+
style: { fontSize: options.typeSize ?? 72, fontFamily: options.typeFamily || "sans-serif" },
|
|
13871
|
+
mode: selectionModeFromModifiers(modifiers, options.mode),
|
|
13872
|
+
feather: options.feather ?? 0,
|
|
13873
|
+
antiAlias: options.antiAlias
|
|
13874
|
+
});
|
|
13875
|
+
} catch (err) {
|
|
13876
|
+
this.error = err instanceof Error ? err.message : String(err);
|
|
13877
|
+
}
|
|
13878
|
+
return;
|
|
13879
|
+
}
|
|
13792
13880
|
if (options.tool === "wand" || options.tool === "range") {
|
|
13793
13881
|
this.start = null;
|
|
13794
13882
|
const common = {
|
|
@@ -16185,7 +16273,13 @@ var STYLE = {
|
|
|
16185
16273
|
leading: { type: ["number", "null"], minimum: 0, maximum: 1e4, description: "Baseline-to-baseline distance in pixels (null = auto, the paragraph autoLeading \xD7 size)." },
|
|
16186
16274
|
baselineShift: { type: ["number", "null"], minimum: -5e3, maximum: 5e3, description: "Pixels; positive raises the text (null resets to 0)." },
|
|
16187
16275
|
underline: { type: "boolean", description: "Underline." },
|
|
16188
|
-
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."
|
|
16189
16283
|
};
|
|
16190
16284
|
var PARAGRAPH = {
|
|
16191
16285
|
align: { type: "string", enum: ["left", "center", "right", "justify"], description: "Alignment (justify stretches paragraph-box lines but the last)." },
|
|
@@ -16224,7 +16318,7 @@ function createImageTypeTools(controller) {
|
|
|
16224
16318
|
const get = {
|
|
16225
16319
|
name: "get_text_layer",
|
|
16226
16320
|
title: "Read a type layer",
|
|
16227
|
-
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.",
|
|
16228
16322
|
inputSchema: { type: "object", properties: { layerId: LAYER_ID6 }, required: ["layerId"], additionalProperties: false },
|
|
16229
16323
|
annotations: { title: "Read a type layer", ...READ11 },
|
|
16230
16324
|
handler: ({ layerId }) => controller.getTextLayer(typeId(layerId))
|
|
@@ -16232,7 +16326,7 @@ function createImageTypeTools(controller) {
|
|
|
16232
16326
|
const add2 = {
|
|
16233
16327
|
name: "add_text_layer",
|
|
16234
16328
|
title: "Add a type layer",
|
|
16235
|
-
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.",
|
|
16236
16330
|
inputSchema: {
|
|
16237
16331
|
type: "object",
|
|
16238
16332
|
properties: {
|
|
@@ -16248,6 +16342,7 @@ function createImageTypeTools(controller) {
|
|
|
16248
16342
|
},
|
|
16249
16343
|
style: { type: "object", description: "Character style.", properties: STYLE, additionalProperties: false },
|
|
16250
16344
|
paragraph: { type: "object", description: "Paragraph style.", properties: PARAGRAPH, additionalProperties: false },
|
|
16345
|
+
orientation: ORIENTATION,
|
|
16251
16346
|
rotation: { type: "number", description: "Degrees clockwise about the origin (default 0)." },
|
|
16252
16347
|
name: { type: "string", description: "Layer name (default the start of the text)." },
|
|
16253
16348
|
opacity: { type: "number", minimum: 0, maximum: 1, description: "Layer opacity 0..1 (default 1)." },
|
|
@@ -16262,7 +16357,7 @@ function createImageTypeTools(controller) {
|
|
|
16262
16357
|
},
|
|
16263
16358
|
annotations: { title: "Add a type layer", ...WRITE9 },
|
|
16264
16359
|
handler: (args) => {
|
|
16265
|
-
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"]);
|
|
16266
16361
|
if (init.blend !== void 0) init.blend = init.blend;
|
|
16267
16362
|
const id = controller.addTextLayer(init);
|
|
16268
16363
|
return { layer: layerSummary(id), text: controller.getTextLayer(id) };
|
|
@@ -16322,6 +16417,14 @@ function createImageTypeTools(controller) {
|
|
|
16322
16417
|
return controller.setTextFrame(id, kind === "box" ? { kind: "box", width, height } : { kind: "point" });
|
|
16323
16418
|
}
|
|
16324
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
|
+
};
|
|
16325
16428
|
const toShape = {
|
|
16326
16429
|
name: "convert_text_to_shape",
|
|
16327
16430
|
title: "Convert text to a shape",
|
|
@@ -16333,7 +16436,43 @@ function createImageTypeTools(controller) {
|
|
|
16333
16436
|
return { layer: layerSummary(id), shape: controller.getShapeLayer(id), warnings };
|
|
16334
16437
|
}
|
|
16335
16438
|
};
|
|
16336
|
-
|
|
16439
|
+
const typeMask = {
|
|
16440
|
+
name: "select_text_shape",
|
|
16441
|
+
title: "Select the shape of text",
|
|
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.",
|
|
16443
|
+
inputSchema: {
|
|
16444
|
+
type: "object",
|
|
16445
|
+
properties: {
|
|
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)." },
|
|
16450
|
+
box: {
|
|
16451
|
+
type: "object",
|
|
16452
|
+
description: "Wrap in this box, pixels (vertical: columns fill it from its right edge).",
|
|
16453
|
+
properties: { width: { type: "number", minimum: 1, description: "Box width, pixels." }, height: { type: "number", minimum: 1, description: "Box height, pixels." } },
|
|
16454
|
+
required: ["width", "height"],
|
|
16455
|
+
additionalProperties: false
|
|
16456
|
+
},
|
|
16457
|
+
style: { type: "object", description: "Character style (size in px, family, weight, tracking\u2026; colour is ignored).", properties: STYLE, additionalProperties: false },
|
|
16458
|
+
paragraph: { type: "object", description: "Paragraph style (alignment, leading\u2026).", properties: PARAGRAPH, additionalProperties: false },
|
|
16459
|
+
rotation: { type: "number", description: "Degrees clockwise about the origin (default 0)." },
|
|
16460
|
+
mode: { type: "string", enum: ["replace", "add", "subtract", "intersect"], description: "How it combines with the current selection (default replace)." },
|
|
16461
|
+
feather: { type: "number", minimum: 0, maximum: 1e3, description: "Feather radius in px (default 0)." },
|
|
16462
|
+
antiAlias: { type: "boolean", description: "Soft glyph edges (default true)." }
|
|
16463
|
+
},
|
|
16464
|
+
required: ["text", "x", "y"],
|
|
16465
|
+
additionalProperties: false
|
|
16466
|
+
},
|
|
16467
|
+
annotations: { title: "Select the shape of text", ...WRITE9 },
|
|
16468
|
+
handler: (args) => {
|
|
16469
|
+
const init = pick2(args, ["text", "x", "y", "orientation", "box", "style", "paragraph", "rotation", "mode", "feather", "antiAlias"]);
|
|
16470
|
+
controller.selectTextShape(init);
|
|
16471
|
+
const sel = controller.getSelection();
|
|
16472
|
+
return { empty: !sel, bounds: sel?.bounds ?? null, area: Math.round(sel ? selectionArea(sel) : 0) };
|
|
16473
|
+
}
|
|
16474
|
+
};
|
|
16475
|
+
return [listFonts, get, add2, setText, setStyle, setParagraph, setFrame, setOrientation, toShape, typeMask];
|
|
16337
16476
|
}
|
|
16338
16477
|
|
|
16339
16478
|
// src/image-editor/tools.ts
|
|
@@ -18472,6 +18611,7 @@ export {
|
|
|
18472
18611
|
StrokeCoverage,
|
|
18473
18612
|
SurfaceDraft,
|
|
18474
18613
|
TEXT_ALIGNS,
|
|
18614
|
+
TEXT_ORIENTATIONS,
|
|
18475
18615
|
TEXT_RENDER_MARGIN,
|
|
18476
18616
|
TEXT_STYLE_FIELDS,
|
|
18477
18617
|
TILE,
|
|
@@ -19205,6 +19345,7 @@ export {
|
|
|
19205
19345
|
temperatureToKelvin,
|
|
19206
19346
|
textIndexAt,
|
|
19207
19347
|
textMatrix,
|
|
19348
|
+
textOrientation,
|
|
19208
19349
|
textOutlines,
|
|
19209
19350
|
textRange,
|
|
19210
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
|
-
/**
|
|
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
|
-
/**
|
|
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). */
|