@pixerate/editor 0.33.0 → 0.35.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/THIRD_PARTY_NOTICES.md +22 -0
- package/dist/{bezier-DJPYiVbA.d.ts → bezier-BvqVmWMg.d.ts} +1 -1
- package/dist/{bezier-6KPx3w7Z.d.cts → bezier-D8bsO-L0.d.cts} +1 -1
- package/dist/canvas/index.cjs +179 -622
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +60 -3
- package/dist/canvas/index.d.ts +60 -3
- package/dist/canvas/index.js +37 -480
- package/dist/canvas/index.js.map +1 -1
- package/dist/{chunk-M4XE4UMT.cjs → chunk-BGNPT5PE.cjs} +464 -5
- package/dist/chunk-BGNPT5PE.cjs.map +1 -0
- package/dist/{chunk-GQTXV2EQ.js → chunk-EGPIVUEF.js} +470 -11
- package/dist/chunk-EGPIVUEF.js.map +1 -0
- package/dist/vector/index.cjs +2776 -185
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +638 -10
- package/dist/vector/index.d.ts +638 -10
- package/dist/vector/index.js +2644 -53
- package/dist/vector/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-GQTXV2EQ.js.map +0 -1
- package/dist/chunk-M4XE4UMT.cjs.map +0 -1
package/dist/vector/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as CanvasGradientDef, A as AffineMatrix, B as BezierPathInput, a as BezierPath, S as SvgGradientDef } from '../bezier-
|
|
1
|
+
import { C as CanvasGradientDef, A as AffineMatrix, B as BezierPathInput, a as BezierPath, S as SvgGradientDef } from '../bezier-BvqVmWMg.js';
|
|
2
2
|
import { P as Point } from '../types-BFkYA4eF.js';
|
|
3
3
|
import { H as HistoryManager } from '../HistoryManager-DWSLd6Tf.js';
|
|
4
4
|
import { C as CommandSpec } from '../registry-DhVUZioj.js';
|
|
@@ -109,8 +109,12 @@ interface VectorAnchorRef {
|
|
|
109
109
|
interface VectorHandleRef extends VectorAnchorRef {
|
|
110
110
|
handle: 'in' | 'out';
|
|
111
111
|
}
|
|
112
|
-
/**
|
|
113
|
-
|
|
112
|
+
/**
|
|
113
|
+
* Canvas tools. `direct` edits anchors, handles and segments; the shape tools drag out a new
|
|
114
|
+
* shape; `scissors` cuts a path at a point, `knife` cuts filled shapes along a freehand stroke
|
|
115
|
+
* and `eraser` rubs out the area under one.
|
|
116
|
+
*/
|
|
117
|
+
type VectorTool = 'select' | 'direct' | 'pen' | 'pencil' | 'rect' | 'ellipse' | 'polygon' | 'star' | 'line' | 'scissors' | 'knife' | 'eraser';
|
|
114
118
|
declare const VECTOR_TOOLS: readonly VectorTool[];
|
|
115
119
|
/** Keyboard modifiers held during a pointer event. */
|
|
116
120
|
interface VectorModifiers {
|
|
@@ -144,6 +148,14 @@ type VectorAlign = 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom';
|
|
|
144
148
|
type VectorDistribute = 'horizontal' | 'vertical';
|
|
145
149
|
type VectorBooleanOperation = 'union' | 'subtract' | 'intersect' | 'exclude';
|
|
146
150
|
type VectorArrange = 'front' | 'forward' | 'backward' | 'back';
|
|
151
|
+
/** Average: line anchors up on a horizontal line (same y), a vertical one (same x), or both. */
|
|
152
|
+
type VectorAverageAxis = 'horizontal' | 'vertical' | 'both';
|
|
153
|
+
/** Identifies one segment of a path node: from anchor `segment` to the next. */
|
|
154
|
+
interface VectorSegmentRef {
|
|
155
|
+
nodeId: string;
|
|
156
|
+
subpath: number;
|
|
157
|
+
segment: number;
|
|
158
|
+
}
|
|
147
159
|
|
|
148
160
|
/**
|
|
149
161
|
* Vector path geometry: anchors and handles to Bézier paths and back, bounds, hit-testing,
|
|
@@ -339,10 +351,245 @@ declare function parseSvgTransform(value: string | undefined): AffineMatrix;
|
|
|
339
351
|
/** Parses SVG markup into a vector document. Throws when there is no `<svg>` element. */
|
|
340
352
|
declare function parseVectorSvg(svg: string, options?: VectorSvgImportOptions): VectorDocument;
|
|
341
353
|
|
|
354
|
+
/**
|
|
355
|
+
* What a guide line shows: `align` lines run from a target through the snapped point or box,
|
|
356
|
+
* `construction` lines from where a drawn point leaves, `spacing` marks equal gaps and `size`
|
|
357
|
+
* the side whose length matches another object's.
|
|
358
|
+
*/
|
|
359
|
+
type VectorGuideKind = 'align' | 'construction' | 'spacing' | 'size';
|
|
360
|
+
/** A guide line in document units. */
|
|
361
|
+
interface VectorGuideLine {
|
|
362
|
+
kind: VectorGuideKind;
|
|
363
|
+
x1: number;
|
|
364
|
+
y1: number;
|
|
365
|
+
x2: number;
|
|
366
|
+
y2: number;
|
|
367
|
+
}
|
|
368
|
+
/** What a point or box snapped to. */
|
|
369
|
+
type VectorSnapKind = 'anchor' | 'centre' | 'intersect' | 'perpendicular' | 'tangent' | 'path' | 'construction' | 'align' | 'spacing' | 'size';
|
|
370
|
+
/** A guide label in document units: the snap kind's name, or a distance for gaps and sizes. */
|
|
371
|
+
interface VectorGuideLabel {
|
|
372
|
+
kind: VectorSnapKind;
|
|
373
|
+
x: number;
|
|
374
|
+
y: number;
|
|
375
|
+
text: string;
|
|
376
|
+
}
|
|
377
|
+
interface VectorSnapGuides {
|
|
378
|
+
lines: VectorGuideLine[];
|
|
379
|
+
labels: VectorGuideLabel[];
|
|
380
|
+
}
|
|
381
|
+
interface VectorPointSnap extends VectorSnapGuides {
|
|
382
|
+
point: Vec2;
|
|
383
|
+
/** The rule that placed the point, or null when nothing was in reach. */
|
|
384
|
+
kind: VectorSnapKind | null;
|
|
385
|
+
/** Whether x / y were set by a target (for falling back to the grid on the other axis). */
|
|
386
|
+
x: boolean;
|
|
387
|
+
y: boolean;
|
|
388
|
+
}
|
|
389
|
+
interface VectorRectSnap extends VectorSnapGuides {
|
|
390
|
+
/** Correction to add to the move. */
|
|
391
|
+
dx: number;
|
|
392
|
+
dy: number;
|
|
393
|
+
x: boolean;
|
|
394
|
+
y: boolean;
|
|
395
|
+
}
|
|
396
|
+
interface VectorScaleSnap extends VectorSnapGuides {
|
|
397
|
+
sx: number;
|
|
398
|
+
sy: number;
|
|
399
|
+
snapped: boolean;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* The point a drawn point leaves from (the anchor before it, a shape's start, a handle's
|
|
403
|
+
* anchor) and how it keeps to it.
|
|
404
|
+
*/
|
|
405
|
+
interface VectorSnapLeave {
|
|
406
|
+
at: Vec2;
|
|
407
|
+
/**
|
|
408
|
+
* Shift held: keep to 45° steps round `at` (`angle`), to a diagonal (`square`, a box's
|
|
409
|
+
* corner) or to the nearer axis (`axis`, a dragged point).
|
|
410
|
+
*/
|
|
411
|
+
constrain?: 'angle' | 'square' | 'axis' | null;
|
|
412
|
+
/** Construction guide angles through `at`, degrees counter-clockwise on screen. */
|
|
413
|
+
angles?: readonly number[];
|
|
414
|
+
/** Snap to the perpendicular foot and tangent points from `at` on paths (default true). */
|
|
415
|
+
curves?: boolean;
|
|
416
|
+
}
|
|
417
|
+
/** The construction guide angles new editors start with. */
|
|
418
|
+
declare const VECTOR_CONSTRUCTION_ANGLES: readonly number[];
|
|
419
|
+
/** Where `constrain` puts `p` (unchanged without one). */
|
|
420
|
+
declare function constrainToLeave(leave: VectorSnapLeave | null | undefined, p: Vec2): Vec2;
|
|
421
|
+
/**
|
|
422
|
+
* Snap targets in document space, gathered once per gesture. Build them with `forMove`,
|
|
423
|
+
* `forResize`, `forDrawing`, `forAnchorDrag` or `forHandle`, then call `snapFrom`,
|
|
424
|
+
* `snapRect` or `snapScale` on every pointer move. Tolerances are in document units (screen
|
|
425
|
+
* pixels divided by the zoom).
|
|
426
|
+
*/
|
|
427
|
+
declare class VectorSnapTargets {
|
|
428
|
+
private readonly points;
|
|
429
|
+
private readonly xs;
|
|
430
|
+
private readonly ys;
|
|
431
|
+
private readonly segments;
|
|
432
|
+
/** Bounds of the objects a moved box spaces itself evenly with. */
|
|
433
|
+
private readonly boxes;
|
|
434
|
+
/** Side lengths of the other objects (in their own frames), which a resize may match. */
|
|
435
|
+
private readonly sizes;
|
|
436
|
+
private constructor();
|
|
437
|
+
/** How many targets of each sort were gathered. */
|
|
438
|
+
get counts(): {
|
|
439
|
+
points: number;
|
|
440
|
+
lines: number;
|
|
441
|
+
segments: number;
|
|
442
|
+
boxes: number;
|
|
443
|
+
};
|
|
444
|
+
/** Targets for moving nodes `ids`: the other art's anchors, bounds and centres, the artboard, and boxes to space evenly with. */
|
|
445
|
+
static forMove(doc: VectorDocument, ids: readonly string[]): VectorSnapTargets;
|
|
446
|
+
/** Targets for resizing nodes `ids`: as for a move, plus the other objects' sizes. */
|
|
447
|
+
static forResize(doc: VectorDocument, ids: readonly string[]): VectorSnapTargets;
|
|
448
|
+
/**
|
|
449
|
+
* Targets for a drawn point (pen, shape tools): the art but `exclude`, its anchors (as
|
|
450
|
+
* points and in line), centres, edges and segments. The anchors and segments of `exclude`
|
|
451
|
+
* (the path being drawn, whose bounds grow with it) stay targets.
|
|
452
|
+
*/
|
|
453
|
+
static forDrawing(doc: VectorDocument, exclude?: readonly string[]): VectorSnapTargets;
|
|
454
|
+
/**
|
|
455
|
+
* Targets for dragging anchors: the other art with its segments, and the anchors and
|
|
456
|
+
* segments that stay put on the paths being reshaped (their bounds move along, so they are
|
|
457
|
+
* no targets). The moving anchors are left out.
|
|
458
|
+
*/
|
|
459
|
+
static forAnchorDrag(doc: VectorDocument, anchors: readonly VectorAnchorRef[]): VectorSnapTargets;
|
|
460
|
+
/**
|
|
461
|
+
* Targets for dragging a handle of path `nodeId`: the other art and that path's anchors
|
|
462
|
+
* (its bounds and the segments through the handle move with it, so they would chase it).
|
|
463
|
+
*/
|
|
464
|
+
static forHandle(doc: VectorDocument, nodeId: string): VectorSnapTargets;
|
|
465
|
+
/** The anchors of the paths `ids` as targets (on them and in line), and their segments when `segments`. */
|
|
466
|
+
private pushPaths;
|
|
467
|
+
private pushAnchor;
|
|
468
|
+
/** The segments of `sp` (mapped by `m`) that stay put while the anchors `moving` accepts move. */
|
|
469
|
+
private pushSegments;
|
|
470
|
+
private pushRect;
|
|
471
|
+
/** Sorts the targets for `within` (stable: of targets alike, the first gathered wins). */
|
|
472
|
+
private index;
|
|
473
|
+
/**
|
|
474
|
+
* Gathers targets from the artboard and every visible node but `exclude` (and what is inside
|
|
475
|
+
* those): each leaf's anchors (also as lines for `drawing`), its segments (`segments`,
|
|
476
|
+
* `drawing`), its bounds' corners as lines and its centre; and the top-level objects' boxes and
|
|
477
|
+
* sizes (inside a group holding an excluded node, that group's other members).
|
|
478
|
+
*/
|
|
479
|
+
private static collect;
|
|
480
|
+
/** Snaps a single point (see `snapFrom`). */
|
|
481
|
+
snapPoint(p: Vec2, tol: number): VectorPointSnap;
|
|
482
|
+
/**
|
|
483
|
+
* Snaps a point `p`, drawn or dragged from `leave` when given. With `leave.constrain` it keeps
|
|
484
|
+
* to its angle round `leave.at`, sliding along that way into line with the nearest target.
|
|
485
|
+
* Otherwise it lands, in order, on an anchor or centre, an intersection of two paths, the
|
|
486
|
+
* perpendicular foot or a tangent point from `leave.at`, a path, a construction guide
|
|
487
|
+
* through `leave.at` (where a target's line crosses it if one does nearby), or else lines up
|
|
488
|
+
* with targets on x and y.
|
|
489
|
+
*/
|
|
490
|
+
snapFrom(p: Vec2, leave: VectorSnapLeave | null | undefined, tol: number): VectorPointSnap;
|
|
491
|
+
private label;
|
|
492
|
+
/** The anchor or centre nearest `p`, within `tol`. */
|
|
493
|
+
private nearestPoint;
|
|
494
|
+
/**
|
|
495
|
+
* Slides `q`, on the line through `at` along `dir` (beyond `at` only for a `ray`), to where
|
|
496
|
+
* the nearest target line crosses it, at most twice `tol` away: where it lands and the
|
|
497
|
+
* target point that line comes from.
|
|
498
|
+
*/
|
|
499
|
+
private slide;
|
|
500
|
+
/** The guides of a point `q` slid into line with the target at `from`: the line and "align", or the target's own label when `q` sits on it. */
|
|
501
|
+
private linedUp;
|
|
502
|
+
/** Target segments whose control box reaches `p` and which pass within `tol` of it, nearest first. */
|
|
503
|
+
private segmentsNear;
|
|
504
|
+
private onSegment;
|
|
505
|
+
/** Where two of the target segments near `p` cross, the crossing nearest `p` within `tol`. */
|
|
506
|
+
private crossing;
|
|
507
|
+
/**
|
|
508
|
+
* The foot of a perpendicular, or a tangent point, from `base` on a target segment near `p`
|
|
509
|
+
* (within `tol` of it): roots of `(B(t) − base) · B′(t)` and `(B(t) − base) × B′(t)`
|
|
510
|
+
* bracketed by sign changes of samples and narrowed by bisection.
|
|
511
|
+
*/
|
|
512
|
+
private curvePoint;
|
|
513
|
+
/**
|
|
514
|
+
* Snaps a moving box `r` (the moved selection's bounds): its edge or centre nearest a target
|
|
515
|
+
* line on each axis (`axes` limits which may move). With `spacing`, an axis that lines up
|
|
516
|
+
* with nothing spaces the box evenly in its row or column. Returns the correction and guides.
|
|
517
|
+
*/
|
|
518
|
+
snapRect(r: VectorBounds, tol: number, options?: {
|
|
519
|
+
spacing?: boolean;
|
|
520
|
+
axes?: {
|
|
521
|
+
x?: boolean;
|
|
522
|
+
y?: boolean;
|
|
523
|
+
};
|
|
524
|
+
}): VectorRectSnap;
|
|
525
|
+
/**
|
|
526
|
+
* Equal spacing along x (`horizontal`) or y for the moved box `r`, among the objects of its
|
|
527
|
+
* row (column): the shift within `tol` that centres it between its neighbours, or leaves it
|
|
528
|
+
* as far from the neighbour before or after it as two other objects of the row are apart;
|
|
529
|
+
* and the gaps that are equal then, as (start, end, where across).
|
|
530
|
+
*/
|
|
531
|
+
private evenSpacing;
|
|
532
|
+
/** A gap mark: a line across the gap with a tick at each end, and its length as a label. */
|
|
533
|
+
private gapMarks;
|
|
534
|
+
/** The other objects' side length nearest `length`, within `tol`, or null. */
|
|
535
|
+
matchSize(length: number, tol: number): number | null;
|
|
536
|
+
/**
|
|
537
|
+
* Snaps a selection-box resize. `sx / sy` are the scale `scaleFor` gave for dragging
|
|
538
|
+
* `handle` of `frame` (in the box's own, possibly rotated frame), `mods.shift` keeps the
|
|
539
|
+
* proportions and `mods.alt` scales about the centre. The handle lands on an anchor or
|
|
540
|
+
* centre within `tol`, else the corner or the side it moves lines up with the nearest
|
|
541
|
+
* target, whatever the box's angle; a handle with one way to go (a side, or a proportional
|
|
542
|
+
* corner) slides along it until one of them is on a target. An axis that snaps to nothing
|
|
543
|
+
* may match another object's width or height instead.
|
|
544
|
+
*/
|
|
545
|
+
snapScale(frame: VectorBounds & {
|
|
546
|
+
angle: number;
|
|
547
|
+
}, handle: Exclude<VectorTransformHandle, 'rotate'>, sx: number, sy: number, mods: {
|
|
548
|
+
shift?: boolean;
|
|
549
|
+
alt?: boolean;
|
|
550
|
+
}, tol: number): VectorScaleSnap;
|
|
551
|
+
}
|
|
552
|
+
|
|
342
553
|
interface VectorSnapOptions {
|
|
343
|
-
/** Grid size in document units (0 = off, default 0). */
|
|
554
|
+
/** Grid size in document units (0 = off, default 0). Points and boxes that snap to no object snap to it. */
|
|
344
555
|
grid: number;
|
|
556
|
+
/**
|
|
557
|
+
* Snap to other objects (default true): anchors, paths and their intersections, bounding-box
|
|
558
|
+
* edges and centres, the artboard, construction angles, equal spacing and matching sizes.
|
|
559
|
+
*/
|
|
560
|
+
objects: boolean;
|
|
561
|
+
/** Show smart guide lines and labels while snapping (default true). */
|
|
562
|
+
guides: boolean;
|
|
563
|
+
/** How near a target pulls, in screen pixels (default 5). */
|
|
564
|
+
threshold: number;
|
|
565
|
+
/** Construction guide angles through the point a drawn point leaves from, in degrees (default 0, 45, 90, 135). */
|
|
566
|
+
angles: readonly number[];
|
|
567
|
+
}
|
|
568
|
+
/** Snap options new editors start with. Hold Cmd / Ctrl (`mod`) during a drag to bypass snapping. */
|
|
569
|
+
declare const DEFAULT_VECTOR_SNAP: Readonly<VectorSnapOptions>;
|
|
570
|
+
/** How path-editing gestures and the pencil, knife and eraser behave. */
|
|
571
|
+
interface VectorPathEditOptions {
|
|
572
|
+
/**
|
|
573
|
+
* Deleting anchors refits the neighbouring handles so the shape stays (default true). Off,
|
|
574
|
+
* the neighbours are joined with their handles as they are.
|
|
575
|
+
*/
|
|
576
|
+
keepShapeOnDelete: boolean;
|
|
577
|
+
/**
|
|
578
|
+
* Dragging one anchor with the direct tool bends its two segments like the Curvature tool,
|
|
579
|
+
* keeping the segments beyond still (default false). Alt held during the drag flips it.
|
|
580
|
+
*/
|
|
581
|
+
curvatureMoves: boolean;
|
|
582
|
+
/** Pencil lazy-mouse smoothing, 0–1: the pulled string is up to 100 screen pixels long (default 0, off). */
|
|
583
|
+
pencilSmoothing: number;
|
|
584
|
+
/** Pencil strokes that look like a line, rectangle, ellipse or polygon become that shape (default false). */
|
|
585
|
+
recognizeShapes: boolean;
|
|
586
|
+
/** Eraser diameter in document units (default 10). */
|
|
587
|
+
eraserSize: number;
|
|
345
588
|
}
|
|
589
|
+
/** Path-editing options new editors start with. */
|
|
590
|
+
declare const DEFAULT_VECTOR_PATH_EDIT: Readonly<VectorPathEditOptions>;
|
|
591
|
+
/** Longest pencil lazy-mouse string (at smoothing 1), in screen pixels. */
|
|
592
|
+
declare const VECTOR_PENCIL_STRING_PX = 100;
|
|
346
593
|
interface VectorEditorOptions {
|
|
347
594
|
document?: VectorDocument;
|
|
348
595
|
/** History to record into, e.g. one shared with the rest of the app (default: a new one). */
|
|
@@ -353,6 +600,7 @@ interface VectorEditorOptions {
|
|
|
353
600
|
defaults?: VectorDefaults;
|
|
354
601
|
viewport?: Partial<VectorViewport>;
|
|
355
602
|
snap?: Partial<VectorSnapOptions>;
|
|
603
|
+
editing?: Partial<VectorPathEditOptions>;
|
|
356
604
|
/** Pick distance for anchors, handles and outlines in screen pixels (default 6). */
|
|
357
605
|
hitRadius?: number;
|
|
358
606
|
/** Id factory for new nodes. */
|
|
@@ -375,6 +623,7 @@ interface VectorHover {
|
|
|
375
623
|
nodeId: string | null;
|
|
376
624
|
anchor?: VectorAnchorRef;
|
|
377
625
|
handle?: VectorHandleRef;
|
|
626
|
+
/** A segment under the pointer (direct tool and scissors); `point` is in document space. */
|
|
378
627
|
segment?: {
|
|
379
628
|
nodeId: string;
|
|
380
629
|
subpath: number;
|
|
@@ -407,11 +656,20 @@ type VectorInteraction = {
|
|
|
407
656
|
} | {
|
|
408
657
|
type: 'handle';
|
|
409
658
|
ref: VectorHandleRef;
|
|
659
|
+
} | {
|
|
660
|
+
type: 'bend';
|
|
661
|
+
ref: VectorSegmentRef;
|
|
410
662
|
} | {
|
|
411
663
|
type: 'draw';
|
|
412
664
|
tool: VectorTool;
|
|
413
665
|
nodeId: string;
|
|
414
666
|
bounds: VectorBounds;
|
|
667
|
+
string?: [Vec2, Vec2];
|
|
668
|
+
} | {
|
|
669
|
+
type: 'stroke';
|
|
670
|
+
tool: 'knife' | 'eraser';
|
|
671
|
+
points: Vec2[];
|
|
672
|
+
width: number;
|
|
415
673
|
} | {
|
|
416
674
|
type: 'pen';
|
|
417
675
|
nodeId: string;
|
|
@@ -435,6 +693,9 @@ interface VectorEditorState {
|
|
|
435
693
|
viewport: VectorViewport;
|
|
436
694
|
defaults: Readonly<Required<Pick<VectorDefaults, 'polygonSides' | 'starPoints' | 'starInnerRatio' | 'cornerRadius'>> & VectorStyle>;
|
|
437
695
|
snap: VectorSnapOptions;
|
|
696
|
+
editing: VectorPathEditOptions;
|
|
697
|
+
/** Smart guides of the snap in progress, in document units (null when there are none). */
|
|
698
|
+
guides: VectorSnapGuides | null;
|
|
438
699
|
hitRadius: number;
|
|
439
700
|
hover: VectorHover | null;
|
|
440
701
|
/** A CSS cursor for the canvas. */
|
|
@@ -570,11 +831,17 @@ declare class VectorEditorController {
|
|
|
570
831
|
private defaults;
|
|
571
832
|
private viewport;
|
|
572
833
|
private snap;
|
|
834
|
+
private editing;
|
|
573
835
|
private hitRadius;
|
|
574
836
|
private hover;
|
|
575
837
|
private pointer;
|
|
576
838
|
private drag;
|
|
577
839
|
private interaction;
|
|
840
|
+
private guides;
|
|
841
|
+
/** Whether the last `snapDrawn` landed on an object (guides may be hidden). */
|
|
842
|
+
private snappedToObject;
|
|
843
|
+
/** Drawing targets for hovering the pen and shape tools, kept while the document and the excluded path stay the same. */
|
|
844
|
+
private hoverTargets;
|
|
578
845
|
private spaceHeld;
|
|
579
846
|
private clipboard;
|
|
580
847
|
private readonly createId;
|
|
@@ -636,8 +903,25 @@ declare class VectorEditorController {
|
|
|
636
903
|
setTool(tool: VectorTool): void;
|
|
637
904
|
setDefaults(defaults: Partial<VectorDefaults>): void;
|
|
638
905
|
setSnap(snap: Partial<VectorSnapOptions>): void;
|
|
906
|
+
/** Changes how deleting, dragging anchors, the pencil and the eraser behave. */
|
|
907
|
+
setEditing(editing: Partial<VectorPathEditOptions>): void;
|
|
908
|
+
/** Turns object snapping on or off (the toolbar's snapping toggle). */
|
|
909
|
+
toggleSnapping(on?: boolean): void;
|
|
910
|
+
private gridValue;
|
|
639
911
|
private snapPoint;
|
|
640
|
-
|
|
912
|
+
/** The pull distance in document units. */
|
|
913
|
+
private snapTolerance;
|
|
914
|
+
private setGuides;
|
|
915
|
+
/**
|
|
916
|
+
* Where a drawn or dragged point `p` goes: onto the smart guide `targets` (gathered by
|
|
917
|
+
* `gather` when missing), else onto the grid, kept to `leave`'s constraint. Cmd / Ctrl
|
|
918
|
+
* bypasses snapping.
|
|
919
|
+
*/
|
|
920
|
+
private snapDrawn;
|
|
921
|
+
/** Drawing targets for the pen and shape tools, reused while the document stays the same. */
|
|
922
|
+
private drawingTargets;
|
|
923
|
+
/** Where the pointer at `p` would place a point with the pen or a shape tool (and the guides showing why). */
|
|
924
|
+
private hoverSnap;
|
|
641
925
|
/** Replaces the document. Undoable unless `{ history: false }` (then history is cleared). */
|
|
642
926
|
setDocument(doc: VectorDocument, options?: {
|
|
643
927
|
history?: boolean;
|
|
@@ -779,8 +1063,22 @@ declare class VectorEditorController {
|
|
|
779
1063
|
private updateAnchors;
|
|
780
1064
|
/** Moves anchors by a document-space offset (converted into each node's own space). */
|
|
781
1065
|
private movedAnchors;
|
|
782
|
-
/**
|
|
783
|
-
|
|
1066
|
+
/**
|
|
1067
|
+
* Moves one anchor to a document position. Its handles follow; with `curvature` (default:
|
|
1068
|
+
* the `curvatureMoves` setting) its two segments bend instead, as the Curvature tool does.
|
|
1069
|
+
*/
|
|
1070
|
+
moveAnchor(ref: VectorAnchorRef, to: Vec2, options?: {
|
|
1071
|
+
curvature?: boolean;
|
|
1072
|
+
}): VectorActionResult;
|
|
1073
|
+
/** `doc` with anchor `ref` moved to document point `to` by a Curvature-tool move. */
|
|
1074
|
+
private curvatureMoved;
|
|
1075
|
+
/** `doc` with segment `ref` bent through document point `p` at parameter `t`. */
|
|
1076
|
+
private bent;
|
|
1077
|
+
/**
|
|
1078
|
+
* Bends a segment so the curve passes through document point `to` at parameter `t`
|
|
1079
|
+
* (default 0.5, clamped to 0.05–0.95); see `bendSegment` in `pathEdit`.
|
|
1080
|
+
*/
|
|
1081
|
+
bendSegment(ref: VectorSegmentRef, to: Vec2, t?: number): VectorActionResult;
|
|
784
1082
|
/** Moves one handle to a document position (see `moveAnchorHandle` for how the opposite handle follows). */
|
|
785
1083
|
moveHandle(ref: VectorHandleRef, to: Vec2, options?: {
|
|
786
1084
|
breakHandles?: boolean;
|
|
@@ -789,12 +1087,95 @@ declare class VectorEditorController {
|
|
|
789
1087
|
convertAnchors(type: VectorAnchorType, refs?: readonly VectorAnchorRef[]): VectorActionResult;
|
|
790
1088
|
/** Adds an anchor on the nearest segment of `nodeId` to document point `point` (shape unchanged). */
|
|
791
1089
|
insertAnchorAt(nodeId: string, point: Vec2): VectorAnchorRef | null;
|
|
792
|
-
/**
|
|
793
|
-
|
|
1090
|
+
/**
|
|
1091
|
+
* Deletes the selected (or given) anchors; subpaths left with one anchor and empty paths go
|
|
1092
|
+
* too. With `keepShape` (default: the `keepShapeOnDelete` setting, on) the neighbours'
|
|
1093
|
+
* handles are refitted so the path keeps its shape; off, the neighbours are joined as they are.
|
|
1094
|
+
*/
|
|
1095
|
+
deleteAnchors(refs?: readonly VectorAnchorRef[], options?: {
|
|
1096
|
+
keepShape?: boolean;
|
|
1097
|
+
}): VectorActionResult;
|
|
794
1098
|
/** Opens or closes the subpaths that contain selected anchors (or all subpaths of `nodeId`). */
|
|
795
1099
|
setClosed(closed: boolean, nodeId?: string): VectorActionResult;
|
|
796
1100
|
/** Reverses the direction of every subpath of the selected paths. */
|
|
797
1101
|
reversePaths(ids?: readonly string[]): VectorActionResult;
|
|
1102
|
+
/** Unlocked path nodes in the given roots (default: the paths being edited, else the selection). */
|
|
1103
|
+
private pathTargets;
|
|
1104
|
+
/** Subpaths of node `from` mapped into node `to`'s own space. */
|
|
1105
|
+
private subpathsIn;
|
|
1106
|
+
/**
|
|
1107
|
+
* Replaces a path with pieces: each entry becomes one path (the first keeps the node's id and
|
|
1108
|
+
* place, the others go just above it with the same style). No pieces removes the path.
|
|
1109
|
+
* Returns the ids of the paths now standing in for it.
|
|
1110
|
+
*/
|
|
1111
|
+
private replaceWithPieces;
|
|
1112
|
+
/** Clears anchor selections, editing and pen state that no longer point at anything. */
|
|
1113
|
+
private dropStaleRefs;
|
|
1114
|
+
/**
|
|
1115
|
+
* Join: the open subpaths of the selected (or given) paths become one open path, joined
|
|
1116
|
+
* nearest endpoints first (ends within `tolerance` document units merge into one anchor,
|
|
1117
|
+
* others get a straight segment); a single open subpath is closed. The result replaces the
|
|
1118
|
+
* lowest path, in its space and style. Default tolerance: the pick distance.
|
|
1119
|
+
*/
|
|
1120
|
+
joinPaths(options?: {
|
|
1121
|
+
ids?: readonly string[];
|
|
1122
|
+
tolerance?: number;
|
|
1123
|
+
}): VectorActionResult;
|
|
1124
|
+
/** Average: moves the selected (or given) anchors onto their average position along `axis`, in document space. */
|
|
1125
|
+
averageAnchors(axis?: VectorAverageAxis, refs?: readonly VectorAnchorRef[]): VectorActionResult;
|
|
1126
|
+
/** Applies `fn` to every subpath of the target paths as one undo step. */
|
|
1127
|
+
private editSubpaths;
|
|
1128
|
+
/**
|
|
1129
|
+
* Remove Redundant Points: drops anchors of the selected (or given) paths that can go
|
|
1130
|
+
* without moving the outline more than `tolerance` document units (default 0.5).
|
|
1131
|
+
*/
|
|
1132
|
+
removeRedundantPoints(options?: {
|
|
1133
|
+
ids?: readonly string[];
|
|
1134
|
+
tolerance?: number;
|
|
1135
|
+
}): VectorActionResult;
|
|
1136
|
+
/**
|
|
1137
|
+
* Smooth: pulls handles towards smooth tangents by `amount` (0–1, default 1). With the direct
|
|
1138
|
+
* tool and points selected, only those points change.
|
|
1139
|
+
*/
|
|
1140
|
+
smoothPaths(options?: {
|
|
1141
|
+
ids?: readonly string[];
|
|
1142
|
+
amount?: number;
|
|
1143
|
+
refs?: readonly VectorAnchorRef[];
|
|
1144
|
+
}): VectorActionResult;
|
|
1145
|
+
/** Splits a cut subpath into pieces: separate paths for a one-subpath node, subpaths in place for a compound one. */
|
|
1146
|
+
private applyCuts;
|
|
1147
|
+
/**
|
|
1148
|
+
* Scissors: cuts path `nodeId` at the outline point nearest document point `point` (at an
|
|
1149
|
+
* anchor when within the pick distance of one). A closed subpath opens there; an open one
|
|
1150
|
+
* splits in two (a one-subpath path becomes two paths). Returns the ids of the paths.
|
|
1151
|
+
*/
|
|
1152
|
+
cutPathAt(nodeId: string, point: Vec2): string[] | null;
|
|
1153
|
+
/** Scissors on the selected (or given) anchors: each cuts its subpath there (see `cutPathAt`). */
|
|
1154
|
+
cutAtAnchors(refs?: readonly VectorAnchorRef[]): VectorActionResult;
|
|
1155
|
+
/** Visible, unlocked paths a stroke over `points` can reach: in `ids`, the selection, or (with neither) any whose bounds it crosses. */
|
|
1156
|
+
private strokeTargets;
|
|
1157
|
+
/** A stroke's points in node `id`'s own space. */
|
|
1158
|
+
private localPoints;
|
|
1159
|
+
/**
|
|
1160
|
+
* Knife: cuts closed paths along the polyline `points` (document space) wherever it crosses
|
|
1161
|
+
* them from edge to edge, with no gap between the pieces. It cuts the given paths, the
|
|
1162
|
+
* selection, or (with neither) every path it crosses. Returns the ids of the pieces (empty
|
|
1163
|
+
* when nothing was cut).
|
|
1164
|
+
*/
|
|
1165
|
+
knife(points: readonly Vec2[], options?: {
|
|
1166
|
+
ids?: readonly string[];
|
|
1167
|
+
}): string[];
|
|
1168
|
+
/**
|
|
1169
|
+
* Eraser: rubs out a round stroke of diameter `size` (default: the `eraserSize` setting)
|
|
1170
|
+
* along `points` (document space). Filled closed paths lose that area (pieces that come
|
|
1171
|
+
* apart become separate paths); outlines are cut where they pass under it. It erases from
|
|
1172
|
+
* the given paths, the selection, or (with neither) every path it reaches. Returns the ids
|
|
1173
|
+
* of the paths it changed or created.
|
|
1174
|
+
*/
|
|
1175
|
+
erase(points: readonly Vec2[], options?: {
|
|
1176
|
+
ids?: readonly string[];
|
|
1177
|
+
size?: number;
|
|
1178
|
+
}): string[];
|
|
798
1179
|
/** Ends the pen path being drawn (a lone anchor is removed). */
|
|
799
1180
|
finishPath(): void;
|
|
800
1181
|
/** Copies the selection. Returns JSON text for the system clipboard (or null). */
|
|
@@ -822,6 +1203,8 @@ declare class VectorEditorController {
|
|
|
822
1203
|
/** Endpoints of open subpaths of unlocked visible paths (pen tool resumes from them). */
|
|
823
1204
|
private openEndpoints;
|
|
824
1205
|
private computeHover;
|
|
1206
|
+
/** The nearest outline point of any visible, unlocked path within the pick distance of document point `p`. */
|
|
1207
|
+
private nearestOutline;
|
|
825
1208
|
private sameHover;
|
|
826
1209
|
/** Primary button down on the canvas at `screen` (pixels relative to the canvas). */
|
|
827
1210
|
pointerDown(screen: Vec2, input?: VectorPointerInput): void;
|
|
@@ -832,6 +1215,12 @@ declare class VectorEditorController {
|
|
|
832
1215
|
private downShape;
|
|
833
1216
|
/** Pointer moved over the canvas (with or without a button down). */
|
|
834
1217
|
pointerMove(screen: Vec2, input?: VectorPointerInput): void;
|
|
1218
|
+
/** Snaps a move of the selection by (dx, dy): its bounds line up with targets or space evenly, else go to the grid. */
|
|
1219
|
+
private snapMove;
|
|
1220
|
+
/** The anchor a point drag snaps by, where it started: the grabbed one, else the moving one nearest the press. */
|
|
1221
|
+
private leadAnchor;
|
|
1222
|
+
/** A shape's dragged corner moved so its width or height matches another object's, when one is within reach. */
|
|
1223
|
+
private matchShapeSize;
|
|
835
1224
|
/** Primary button released. */
|
|
836
1225
|
pointerUp(screen?: Vec2, input?: VectorPointerInput): void;
|
|
837
1226
|
/** The pointer left the canvas. */
|
|
@@ -910,6 +1299,21 @@ interface VectorRenderHandle {
|
|
|
910
1299
|
anchorY: number;
|
|
911
1300
|
hovered: boolean;
|
|
912
1301
|
}
|
|
1302
|
+
/** A smart guide line in screen pixels. */
|
|
1303
|
+
interface VectorRenderGuideLine {
|
|
1304
|
+
kind: VectorGuideKind;
|
|
1305
|
+
x1: number;
|
|
1306
|
+
y1: number;
|
|
1307
|
+
x2: number;
|
|
1308
|
+
y2: number;
|
|
1309
|
+
}
|
|
1310
|
+
/** A smart guide label ("anchor", "intersect", "align", "centre", a gap or a size) at a screen position. */
|
|
1311
|
+
interface VectorRenderGuideLabel {
|
|
1312
|
+
kind: VectorSnapKind;
|
|
1313
|
+
x: number;
|
|
1314
|
+
y: number;
|
|
1315
|
+
text: string;
|
|
1316
|
+
}
|
|
913
1317
|
interface VectorOverlayRenderData {
|
|
914
1318
|
/** Outlines (screen-space path data) of hovered and selected nodes. */
|
|
915
1319
|
outlines: {
|
|
@@ -936,6 +1340,29 @@ interface VectorOverlayRenderData {
|
|
|
936
1340
|
penPreview: string | null;
|
|
937
1341
|
/** Artboard rectangle, screen space. */
|
|
938
1342
|
artboard: VectorBounds;
|
|
1343
|
+
/** Smart guides of the snap in progress, screen space (empty when nothing snapped). */
|
|
1344
|
+
guides: {
|
|
1345
|
+
lines: VectorRenderGuideLine[];
|
|
1346
|
+
labels: VectorRenderGuideLabel[];
|
|
1347
|
+
};
|
|
1348
|
+
/**
|
|
1349
|
+
* The knife or eraser stroke being drawn, screen space: `d` is an open polyline; draw the
|
|
1350
|
+
* eraser's with a round-capped stroke `width` pixels wide (0 for the knife: a thin line).
|
|
1351
|
+
*/
|
|
1352
|
+
toolStroke: {
|
|
1353
|
+
tool: 'knife' | 'eraser';
|
|
1354
|
+
d: string;
|
|
1355
|
+
width: number;
|
|
1356
|
+
} | null;
|
|
1357
|
+
/** The pencil's lazy-mouse string from the pen to the pointer, screen space. */
|
|
1358
|
+
pencilString: {
|
|
1359
|
+
x1: number;
|
|
1360
|
+
y1: number;
|
|
1361
|
+
x2: number;
|
|
1362
|
+
y2: number;
|
|
1363
|
+
} | null;
|
|
1364
|
+
/** Where the scissors would cut (screen space). */
|
|
1365
|
+
cutPoint: Vec2 | null;
|
|
939
1366
|
/** A short status, e.g. "W 120 × H 80" or "45°". */
|
|
940
1367
|
status: string | null;
|
|
941
1368
|
}
|
|
@@ -951,8 +1378,12 @@ declare function getVectorOverlayRenderData(state: VectorEditorState): VectorOve
|
|
|
951
1378
|
/** Colours and sizes (screen pixels) the bundled canvases draw the overlay with. */
|
|
952
1379
|
declare const VECTOR_OVERLAY_THEME: {
|
|
953
1380
|
readonly accent: "#0ea5e9";
|
|
1381
|
+
/** Smart guide lines and labels. */
|
|
1382
|
+
readonly guide: "#ff3dfc";
|
|
954
1383
|
readonly handleFill: "#ffffff";
|
|
955
1384
|
readonly marqueeFill: "rgba(14, 165, 233, 0.08)";
|
|
1385
|
+
/** The eraser's swath while it is dragged. */
|
|
1386
|
+
readonly eraserFill: "rgba(239, 68, 68, 0.25)";
|
|
956
1387
|
readonly transformHandleSize: 8;
|
|
957
1388
|
readonly anchorSize: 7;
|
|
958
1389
|
readonly handleRadius: 3.5;
|
|
@@ -1007,6 +1438,25 @@ interface VectorSelectionStyle {
|
|
|
1007
1438
|
declare function getVectorSelectionStyle(state: Pick<VectorEditorState, 'document' | 'selection'>): VectorSelectionStyle | null;
|
|
1008
1439
|
/** A paint as `#rrggbb` for `<input type="color">`, or null for none, gradients and other CSS colours. */
|
|
1009
1440
|
declare function vectorPaintToHex(paint: VectorPaint | undefined): string | null;
|
|
1441
|
+
/** A path-editing button of the bundled toolbars. */
|
|
1442
|
+
interface VectorPathAction {
|
|
1443
|
+
id: 'join' | 'average' | 'cut' | 'clean' | 'smooth';
|
|
1444
|
+
label: string;
|
|
1445
|
+
title: string;
|
|
1446
|
+
/** Shortcut after Cmd / Ctrl, if any. */
|
|
1447
|
+
shortcut?: string;
|
|
1448
|
+
/** Whether it can run with `selected` nodes and `points` selected anchors (direct tool). */
|
|
1449
|
+
enabled: (selected: number, points: number) => boolean;
|
|
1450
|
+
run: (controller: VectorEditorController) => unknown;
|
|
1451
|
+
}
|
|
1452
|
+
/** Join, Average, Cut at Points, Remove Redundant Points and Smooth, as the toolbars show them. */
|
|
1453
|
+
declare const VECTOR_PATH_ACTIONS: readonly VectorPathAction[];
|
|
1454
|
+
/** The on / off path-editing settings the toolbars toggle. */
|
|
1455
|
+
declare const VECTOR_EDIT_TOGGLES: readonly {
|
|
1456
|
+
key: 'keepShapeOnDelete' | 'curvatureMoves' | 'recognizeShapes';
|
|
1457
|
+
label: string;
|
|
1458
|
+
title: string;
|
|
1459
|
+
}[];
|
|
1010
1460
|
|
|
1011
1461
|
interface VectorCommandOptions {
|
|
1012
1462
|
/** Id prefix (default `vector.`); use one per editor when several are registered. */
|
|
@@ -1049,4 +1499,182 @@ interface VectorNodeListing {
|
|
|
1049
1499
|
*/
|
|
1050
1500
|
declare function createVectorCommands(controller: VectorEditorController, options?: VectorCommandOptions): CommandSpec[];
|
|
1051
1501
|
|
|
1052
|
-
|
|
1502
|
+
/**
|
|
1503
|
+
* Removes anchor `index` without opening the path: its neighbours keep their handle directions
|
|
1504
|
+
* and their facing handles are refitted so one cubic follows the two segments that met there
|
|
1505
|
+
* as closely as possible (least maximum error over where the new curve passes the removed
|
|
1506
|
+
* point). Two straight segments become one; removing an end of an open subpath drops its
|
|
1507
|
+
* segment. Returns the subpath unchanged (a copy) when `index` is out of range.
|
|
1508
|
+
*/
|
|
1509
|
+
declare function removeAnchorKeepingShape(sp: VectorSubpath, index: number): VectorSubpath;
|
|
1510
|
+
/** Removes several anchors of a subpath, keeping the shape (see `removeAnchorKeepingShape`). */
|
|
1511
|
+
declare function removeAnchorsKeepingShape(sp: VectorSubpath, indices: readonly number[]): VectorSubpath;
|
|
1512
|
+
/**
|
|
1513
|
+
* Bends segment `segment` so the curve passes through `p` at parameter `t` (clamped to
|
|
1514
|
+
* 0.05–0.95): its handles go to the thirds of the chord plus one shared offset, so
|
|
1515
|
+
* `B(t) = L(t) + 3t(1 − t)·offset` exactly. The end anchors keep their types (a smooth or
|
|
1516
|
+
* symmetric end turns its other handle to stay in line).
|
|
1517
|
+
*/
|
|
1518
|
+
declare function bendSegment(sp: VectorSubpath, segment: number, t: number, p: Vec2): VectorSubpath;
|
|
1519
|
+
/** The point at parameter `t` of segment `segment` (for tests and previews). */
|
|
1520
|
+
declare function subpathPointAt(sp: VectorSubpath, segment: number, t: number): Vec2;
|
|
1521
|
+
/**
|
|
1522
|
+
* Moves anchor `index` to `q` the way the Curvature tool drags a point: only the two segments
|
|
1523
|
+
* at it change. A smooth or symmetric anchor turns its handles along the line through its
|
|
1524
|
+
* neighbours; the neighbours' handles on those segments, and a corner's own handles, keep
|
|
1525
|
+
* their directions while their lengths scale with their segment's chord, so the segments
|
|
1526
|
+
* beyond don't move and a corner without handles keeps none.
|
|
1527
|
+
*/
|
|
1528
|
+
declare function curvatureMoveAnchor(sp: VectorSubpath, index: number, q: Vec2): VectorSubpath;
|
|
1529
|
+
/**
|
|
1530
|
+
* Cuts a subpath at the anchors `at`: each becomes the end of one open piece and the start of
|
|
1531
|
+
* the next, its handle off each piece dropped (the shape doesn't change). A closed subpath
|
|
1532
|
+
* opens at its first cut, so one cut leaves one piece whose ends coincide. The ends of an open
|
|
1533
|
+
* subpath and indices out of range don't cut; with no cut left the subpath comes back as it is.
|
|
1534
|
+
*/
|
|
1535
|
+
declare function cutSubpathAt(sp: VectorSubpath, at: readonly number[]): VectorSubpath[];
|
|
1536
|
+
/**
|
|
1537
|
+
* Cuts a subpath at parameter `t` of segment `segment` (Scissors on a segment): an anchor is
|
|
1538
|
+
* inserted there without changing the shape, then cut. Within `endTolerance` of the segment's
|
|
1539
|
+
* ends (in parameter) the existing anchor is cut instead.
|
|
1540
|
+
*/
|
|
1541
|
+
declare function splitSubpathAt(sp: VectorSubpath, segment: number, t: number, endTolerance?: number): VectorSubpath[];
|
|
1542
|
+
/**
|
|
1543
|
+
* Join: open subpaths are joined nearest-endpoints-first into one open subpath (endpoints
|
|
1544
|
+
* within `tolerance` merge into one anchor, otherwise a straight segment connects them). A
|
|
1545
|
+
* single open subpath is closed instead (its ends merged when they meet). Closed subpaths and
|
|
1546
|
+
* lone anchors pass through unchanged, before the joined one.
|
|
1547
|
+
*/
|
|
1548
|
+
declare function joinSubpaths(subpaths: readonly VectorSubpath[], tolerance: number): VectorSubpath[];
|
|
1549
|
+
/**
|
|
1550
|
+
* Smooth: pulls handles towards Catmull-Rom-like tangents (a third of the way to each
|
|
1551
|
+
* neighbour along the line through both). `amount` 0–1 (0 = unchanged, 1 = fully smooth).
|
|
1552
|
+
* Only the anchors in `only` change when it is given; endpoints of open subpaths keep their
|
|
1553
|
+
* handles. Subpaths of fewer than three anchors are unchanged.
|
|
1554
|
+
*/
|
|
1555
|
+
declare function smoothSubpath(sp: VectorSubpath, amount?: number, only?: ReadonlySet<number>): VectorSubpath;
|
|
1556
|
+
/**
|
|
1557
|
+
* Remove Redundant Points: drops anchors that can go without changing the shape by more than
|
|
1558
|
+
* `tolerance` (collinear corners, duplicate points, and smooth joints that one cubic can
|
|
1559
|
+
* replace).
|
|
1560
|
+
*/
|
|
1561
|
+
declare function removeRedundantPoints(sp: VectorSubpath, tolerance: number): VectorSubpath;
|
|
1562
|
+
|
|
1563
|
+
/**
|
|
1564
|
+
* Knife and eraser on Bézier paths, built on the curve booleans and `outlineStroke`.
|
|
1565
|
+
*
|
|
1566
|
+
* The knife cuts filled regions along a polyline with no gap: each stretch of the polyline
|
|
1567
|
+
* that crosses a region from boundary to boundary (a chord) splits the boundary loop it starts
|
|
1568
|
+
* and ends on into two loops sharing that chord, or, when it joins two loops (an outline and a
|
|
1569
|
+
* hole), merges them into one. Crossings are exact (line–cubic roots), and the pieces share
|
|
1570
|
+
* the cut edge exactly.
|
|
1571
|
+
*
|
|
1572
|
+
* The eraser removes the area of a round-capped stroke along a polyline: filled shapes lose it
|
|
1573
|
+
* by a boolean difference; outlines are cut where they cross the stroke's outline (exact
|
|
1574
|
+
* curve–curve intersections) and keep the parts outside it.
|
|
1575
|
+
*
|
|
1576
|
+
* Modelled on vectorcraft-main/crates/engine/src/cmd/draw2.rs (`knife`, `erase_region`,
|
|
1577
|
+
* `erase_outline`, `cut_subpath`; MIT OR Apache-2.0, © ArtCraft Team and contributors; see
|
|
1578
|
+
* THIRD_PARTY_NOTICES.md), without its fixed knife slit and its sampled crossing search.
|
|
1579
|
+
*/
|
|
1580
|
+
|
|
1581
|
+
type FillRule = 'nonzero' | 'evenodd';
|
|
1582
|
+
/** One path per face (an outline with its holes) of a filled path, largest first. */
|
|
1583
|
+
declare function splitIntoFaces(path: BezierPathInput, fillRule?: FillRule): BezierPath[];
|
|
1584
|
+
/**
|
|
1585
|
+
* Cuts the filled path along the open polyline `knife`. Returns one path per resulting face
|
|
1586
|
+
* (an outline with its holes), or null when the knife crossed nothing from edge to edge. A
|
|
1587
|
+
* stretch of the knife that starts or ends inside the shape does not cut.
|
|
1588
|
+
*/
|
|
1589
|
+
declare function knifePath(path: BezierPathInput, fillRule: FillRule, knife: readonly Point[]): BezierPath[] | null;
|
|
1590
|
+
/** The area a round eraser of diameter `width` covers along `points` (a disc for one point). */
|
|
1591
|
+
declare function eraserRegion(points: readonly Point[], width: number): BezierPath;
|
|
1592
|
+
/**
|
|
1593
|
+
* A filled path with `region` removed: one path per remaining face, or null when the region
|
|
1594
|
+
* does not overlap the fill.
|
|
1595
|
+
*/
|
|
1596
|
+
declare function eraseFromFill(path: BezierPathInput, fillRule: FillRule, region: BezierPathInput): BezierPath[] | null;
|
|
1597
|
+
/**
|
|
1598
|
+
* The parts of a subpath's outline outside `region`, as open subpaths that keep the original
|
|
1599
|
+
* curves exactly; null when the outline does not enter the region. A closed subpath's last
|
|
1600
|
+
* and first parts join at its first anchor.
|
|
1601
|
+
*/
|
|
1602
|
+
declare function eraseFromOutline(sp: VectorSubpath, region: BezierPathInput): VectorSubpath[] | null;
|
|
1603
|
+
/** Bounds of a point list (for picking the paths a knife or eraser stroke can reach). */
|
|
1604
|
+
declare function polylineBounds(points: readonly Point[], pad?: number): {
|
|
1605
|
+
x: number;
|
|
1606
|
+
y: number;
|
|
1607
|
+
width: number;
|
|
1608
|
+
height: number;
|
|
1609
|
+
} | null;
|
|
1610
|
+
/** Ramer–Douglas–Peucker reduction of a polyline (keeps both ends). */
|
|
1611
|
+
declare function simplifyPolyline(points: readonly Point[], tolerance: number): Point[];
|
|
1612
|
+
|
|
1613
|
+
/**
|
|
1614
|
+
* Pencil helpers: lazy-mouse smoothing (a pulled string between the pointer and the pen) and
|
|
1615
|
+
* ink-to-shape recognition (a hand-drawn stroke that is a line, rectangle, ellipse or polygon).
|
|
1616
|
+
*
|
|
1617
|
+
* Portions ported from (MIT OR Apache-2.0, © ArtCraft Team and contributors; see
|
|
1618
|
+
* THIRD_PARTY_NOTICES.md):
|
|
1619
|
+
* - photocraft-main/crates/paint/src/dynamics.rs (`Smoother`: pulled-string mode, `string`,
|
|
1620
|
+
* `finish` with catch-up on stroke end)
|
|
1621
|
+
* - wordcraft-main/crates/engine/src/cmd/ink_shape.rs (`recognise`, `ellipse_rms`,
|
|
1622
|
+
* `snap_square`, `corners`, `turning`, `rdp`, `upright`)
|
|
1623
|
+
*/
|
|
1624
|
+
|
|
1625
|
+
/**
|
|
1626
|
+
* Pulled-string smoothing: the pen stays put until the pointer is more than `length` away,
|
|
1627
|
+
* then follows it at that distance, so small wobbles never reach the stroke. Feed pointer
|
|
1628
|
+
* positions to `push`; it returns the pen positions to draw through (possibly none).
|
|
1629
|
+
*/
|
|
1630
|
+
declare class LazyMouse {
|
|
1631
|
+
readonly length: number;
|
|
1632
|
+
private pos;
|
|
1633
|
+
private last;
|
|
1634
|
+
/** `length` is the string length in the units of the points (0 turns smoothing off). */
|
|
1635
|
+
constructor(length: number);
|
|
1636
|
+
push(p: Point): Point[];
|
|
1637
|
+
/** The string from the pen to the pointer while they are apart, else null. */
|
|
1638
|
+
string(): [Point, Point] | null;
|
|
1639
|
+
/** End of stroke: the pen catches up with the pointer (the point to add, if it lagged). */
|
|
1640
|
+
finish(): Point[];
|
|
1641
|
+
}
|
|
1642
|
+
/** A shape recognised in a stroke, in the stroke's coordinates. */
|
|
1643
|
+
type VectorInkShape = {
|
|
1644
|
+
kind: 'line';
|
|
1645
|
+
a: Point;
|
|
1646
|
+
b: Point;
|
|
1647
|
+
} | {
|
|
1648
|
+
kind: 'rect';
|
|
1649
|
+
x: number;
|
|
1650
|
+
y: number;
|
|
1651
|
+
width: number;
|
|
1652
|
+
height: number;
|
|
1653
|
+
} | {
|
|
1654
|
+
kind: 'ellipse';
|
|
1655
|
+
x: number;
|
|
1656
|
+
y: number;
|
|
1657
|
+
width: number;
|
|
1658
|
+
height: number;
|
|
1659
|
+
} | {
|
|
1660
|
+
kind: 'polygon';
|
|
1661
|
+
points: Point[];
|
|
1662
|
+
};
|
|
1663
|
+
interface RecognizeInkOptions {
|
|
1664
|
+
/** Strokes whose longer side is smaller than this stay ink (default 6). */
|
|
1665
|
+
minSize?: number;
|
|
1666
|
+
}
|
|
1667
|
+
/** Most corners a recognised polygon may have. */
|
|
1668
|
+
declare const VECTOR_INK_MAX_CORNERS = 8;
|
|
1669
|
+
/** "line", "square", "rectangle", "circle", "ellipse", "triangle" or "polygon". */
|
|
1670
|
+
declare function vectorInkShapeName(shape: VectorInkShape): string;
|
|
1671
|
+
/**
|
|
1672
|
+
* The shape a hand-drawn stroke draws, if it is one: an open stroke is a line when it stays
|
|
1673
|
+
* close to the chord between its ends; a closed one is an ellipse when its points sit on the
|
|
1674
|
+
* ellipse inscribed in their bounds, else a polygon of 3–8 corners when that polygon stays
|
|
1675
|
+
* close to every point (an upright four-cornered one is a rectangle). Nearly square boxes
|
|
1676
|
+
* become squares and circles. Anything else (scribbles, curves, letters) is null.
|
|
1677
|
+
*/
|
|
1678
|
+
declare function recognizeInkShape(points: readonly Point[], options?: RecognizeInkOptions): VectorInkShape | null;
|
|
1679
|
+
|
|
1680
|
+
export { type AddVectorNodeOptions, AffineMatrix, DEFAULT_VECTOR_PATH_EDIT, DEFAULT_VECTOR_SNAP, IDENTITY_MATRIX, KAPPA, LazyMouse, type NearestSegment, type RecognizeInkOptions, SvgGradientDef, VECTOR_CLIPBOARD_TYPE, VECTOR_CONSTRUCTION_ANGLES, VECTOR_EDIT_TOGGLES, VECTOR_INK_MAX_CORNERS, VECTOR_OVERLAY_THEME, VECTOR_PATH_ACTIONS, VECTOR_PENCIL_STRING_PX, VECTOR_ROTATE_HANDLE_OFFSET, VECTOR_TOOLS, VECTOR_TOOL_GLYPHS, VECTOR_TOOL_SHORTCUTS, VECTOR_TRANSFORM_HANDLES, type Vec2, type VectorActionResult, type VectorAlign, type VectorAnchor, type VectorAnchorRef, type VectorAnchorType, type VectorArrange, type VectorAverageAxis, type VectorBooleanOperation, type VectorBounds, type VectorCommandOptions, type VectorDefaults, type VectorDistribute, type VectorDocument, VectorEditorController, type VectorEditorOptions, type VectorEditorState, type VectorFillRule, type VectorGroupNode, type VectorGuideKind, type VectorGuideLabel, type VectorGuideLine, type VectorHandleRef, type VectorHover, type VectorInkShape, type VectorInteraction, type VectorKeyInput, type VectorLineCap, type VectorLineJoin, type VectorMatrix, type VectorModifiers, type VectorNode, type VectorNodeListing, type VectorOverlayRenderData, type VectorPaint, type VectorPathAction, type VectorPathEditOptions, type VectorPathNode, type VectorPointSnap, type VectorPointerInput, type VectorRectSnap, type VectorRenderAnchor, type VectorRenderGroup, type VectorRenderGuideLabel, type VectorRenderGuideLine, type VectorRenderHandle, type VectorRenderNode, type VectorRenderPath, type VectorScaleSnap, type VectorSceneRenderData, type VectorSegmentRef, type VectorSelectionBoxGeometry, type VectorSelectionFrame, type VectorSelectionStyle, type VectorShapeInput, type VectorSnapGuides, type VectorSnapKind, type VectorSnapLeave, type VectorSnapOptions, VectorSnapTargets, type VectorStyle, type VectorSubpath, type VectorSvgExportOptions, type VectorSvgImportOptions, type VectorTool, type VectorTransformHandle, type VectorViewport, applyMatrix, applyMatrixLinear, bendSegment, bezierToSubpaths, boundsFromPoints, boundsIntersect, cloneAnchor, cloneSubpath, cloneVectorDocument, cloneVectorNode, collectPathNodes, constrainToLeave, convertAnchor, createVectorCommands, curvatureMoveAnchor, cutSubpathAt, decomposeRigid, ellipseSubpath, eraseFromFill, eraseFromOutline, eraserRegion, findVectorNode, getAnchor, getAnchorWorld, getEditablePathIds, getTransformHandlePositions, getVectorOverlayRenderData, getVectorSceneRenderData, getVectorSelectionBoxGeometry, getVectorSelectionFrame, getVectorSelectionStyle, getVisibleAnchors, getVisibleHandles, hasPaint, hitTestVectorNode, hitTestVectorNodes, inferAnchorType, insertAnchor, invertMatrix, isIdentityMatrix, isVectorTextTarget, joinSubpaths, knifePath, lineSubpath, locateVectorNode, matrixRotation, moveAnchorHandle, multiplyMatrices, nearestSegment, nodeMatrix, parseSvgTransform, parseVectorSvg, polygonSubpath, polylineBounds, recognizeInkShape, rectSubpath, removeAnchorKeepingShape, removeAnchors, removeAnchorsKeepingShape, removeRedundantPoints, reverseSubpath, rotateMatrix, roundSubpaths, scaleFor, scaleMatrix, simplifyPolyline, smoothSubpath, splitIntoFaces, splitSubpathAt, starSubpath, subpathPointAt, subpathSegment, subpathSegmentCount, subpathsToBezier, toVectorKeyInput, toVectorModifiers, toVectorPointerInput, transformVectorNode, translateAnchor, translateMatrix, unionBounds, vectorDocumentToSvg, vectorInkShapeName, vectorNodeBounds, vectorNodeRotation, vectorNodeToBezier, vectorPaintToHex, vectorPaintToSvg, vectorParentMatrix, vectorPathData, vectorPathWorldBezier, vectorResizeCursor, vectorToolLabel, vectorWorldMatrix, walkVectorNodes };
|