@glissade/scene 0.17.0 → 0.17.1-pre.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/path.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { f as PathSeg } from "./displayList.js";
2
+ import { PathValue } from "@glissade/core";
3
+
4
+ //#region src/path.d.ts
5
+
6
+ /**
7
+ * Minimal SVG `<path d>` tokenizer → `PathSeg[]`, kept inside `scene` so it
8
+ * never imports `@glissade/svg` (that would invert the enforced dependency
9
+ * direction, scene ← svg). Handles the common command set: M/m L/l H/h V/v
10
+ * C/c Q/q Z/z (absolute + relative, implicit-repeat per spec). For the FULL set
11
+ * (S/T/A smooth-curves + arcs, with reflection), import a `.svg` through
12
+ * `@glissade/svg`'s `parseSvgPath`; this lean copy covers hand-written `data`
13
+ * strings. Unknown commands are skipped.
14
+ */
15
+ declare function parseSvgPathData(d: string): PathSeg[];
16
+ /**
17
+ * Convenience: an SVG `d` string → `PathValue` (the contour form `Path.data`
18
+ * wants), via `parseSvgPathData` → `pathFromSegs`. Pass the result to a Path:
19
+ * `new Path({ data: pathFromSvg('M0 0 …') })`.
20
+ */
21
+ declare function pathFromSvg(d: string): PathValue;
22
+ //#endregion
23
+ export { parseSvgPathData, pathFromSvg };
package/dist/path.js ADDED
@@ -0,0 +1,135 @@
1
+ import { u as pathFromSegs } from "./nodes.js";
2
+ import "@glissade/core";
3
+ //#region src/path.ts
4
+ /**
5
+ * Minimal SVG `<path d>` tokenizer → `PathSeg[]`, kept inside `scene` so it
6
+ * never imports `@glissade/svg` (that would invert the enforced dependency
7
+ * direction, scene ← svg). Handles the common command set: M/m L/l H/h V/v
8
+ * C/c Q/q Z/z (absolute + relative, implicit-repeat per spec). For the FULL set
9
+ * (S/T/A smooth-curves + arcs, with reflection), import a `.svg` through
10
+ * `@glissade/svg`'s `parseSvgPath`; this lean copy covers hand-written `data`
11
+ * strings. Unknown commands are skipped.
12
+ */
13
+ function parseSvgPathData(d) {
14
+ const tokens = d.match(/[MmLlHhVvCcQqZz]|-?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g) ?? [];
15
+ const segs = [];
16
+ let i = 0;
17
+ let cx = 0;
18
+ let cy = 0;
19
+ let sx = 0;
20
+ let sy = 0;
21
+ let prevCmd = "";
22
+ const num = () => Number(tokens[i++]);
23
+ const isCmd = (t) => !!t && /^[MmLlHhVvCcQqZz]$/.test(t);
24
+ while (i < tokens.length) {
25
+ let cmd = tokens[i];
26
+ if (isCmd(cmd)) i++;
27
+ else cmd = prevCmd === "M" ? "L" : prevCmd === "m" ? "l" : prevCmd;
28
+ if (!cmd) break;
29
+ const rel = cmd === cmd.toLowerCase();
30
+ switch (cmd.toUpperCase()) {
31
+ case "M": {
32
+ const x = num() + (rel ? cx : 0);
33
+ const y = num() + (rel ? cy : 0);
34
+ cx = x;
35
+ cy = y;
36
+ sx = x;
37
+ sy = y;
38
+ segs.push([
39
+ "M",
40
+ x,
41
+ y
42
+ ]);
43
+ break;
44
+ }
45
+ case "L": {
46
+ const x = num() + (rel ? cx : 0);
47
+ const y = num() + (rel ? cy : 0);
48
+ cx = x;
49
+ cy = y;
50
+ segs.push([
51
+ "L",
52
+ x,
53
+ y
54
+ ]);
55
+ break;
56
+ }
57
+ case "H": {
58
+ const x = num() + (rel ? cx : 0);
59
+ cx = x;
60
+ segs.push([
61
+ "L",
62
+ x,
63
+ cy
64
+ ]);
65
+ break;
66
+ }
67
+ case "V": {
68
+ const y = num() + (rel ? cy : 0);
69
+ cy = y;
70
+ segs.push([
71
+ "L",
72
+ cx,
73
+ y
74
+ ]);
75
+ break;
76
+ }
77
+ case "C": {
78
+ const x1 = num() + (rel ? cx : 0);
79
+ const y1 = num() + (rel ? cy : 0);
80
+ const x2 = num() + (rel ? cx : 0);
81
+ const y2 = num() + (rel ? cy : 0);
82
+ const x = num() + (rel ? cx : 0);
83
+ const y = num() + (rel ? cy : 0);
84
+ cx = x;
85
+ cy = y;
86
+ segs.push([
87
+ "C",
88
+ x1,
89
+ y1,
90
+ x2,
91
+ y2,
92
+ x,
93
+ y
94
+ ]);
95
+ break;
96
+ }
97
+ case "Q": {
98
+ const x1 = num() + (rel ? cx : 0);
99
+ const y1 = num() + (rel ? cy : 0);
100
+ const x = num() + (rel ? cx : 0);
101
+ const y = num() + (rel ? cy : 0);
102
+ cx = x;
103
+ cy = y;
104
+ segs.push([
105
+ "Q",
106
+ x1,
107
+ y1,
108
+ x,
109
+ y
110
+ ]);
111
+ break;
112
+ }
113
+ case "Z":
114
+ segs.push(["Z"]);
115
+ cx = sx;
116
+ cy = sy;
117
+ break;
118
+ default:
119
+ i++;
120
+ break;
121
+ }
122
+ prevCmd = cmd;
123
+ }
124
+ return segs;
125
+ }
126
+ /**
127
+ * Convenience: an SVG `d` string → `PathValue` (the contour form `Path.data`
128
+ * wants), via `parseSvgPathData` → `pathFromSegs`. Pass the result to a Path:
129
+ * `new Path({ data: pathFromSvg('M0 0 …') })`.
130
+ */
131
+ function pathFromSvg(d) {
132
+ return pathFromSegs(parseSvgPathData(d));
133
+ }
134
+ //#endregion
135
+ export { parseSvgPathData, pathFromSvg };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glissade/scene",
3
- "version": "0.17.0",
3
+ "version": "0.17.1-pre.0",
4
4
  "description": "glissade scene graph: nodes, transforms, DisplayList emission. Renderer-agnostic; zero DOM/Node dependencies.",
5
5
  "license": "Apache-2.0",
6
6
  "engines": {
@@ -16,6 +16,10 @@
16
16
  "./layout": {
17
17
  "types": "./dist/layout.d.ts",
18
18
  "default": "./dist/layout.js"
19
+ },
20
+ "./path": {
21
+ "types": "./dist/path.d.ts",
22
+ "default": "./dist/path.js"
19
23
  }
20
24
  },
21
25
  "files": [
@@ -23,7 +27,7 @@
23
27
  ],
24
28
  "dependencies": {
25
29
  "yoga-layout": "^3.2.1",
26
- "@glissade/core": "0.17.0"
30
+ "@glissade/core": "0.17.1-pre.0"
27
31
  },
28
32
  "repository": {
29
33
  "type": "git",