lbrnts 0.0.15 → 0.0.17

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/index.d.ts CHANGED
@@ -93,7 +93,7 @@ interface CutSettingInit {
93
93
  lineAngle?: number;
94
94
  crossHatch?: boolean;
95
95
  frequency?: number;
96
- pulseWidth?: number;
96
+ qPulseWidth?: number;
97
97
  }
98
98
  declare class CutSetting extends LightBurnBaseElement {
99
99
  private _type;
@@ -120,7 +120,7 @@ declare class CutSetting extends LightBurnBaseElement {
120
120
  private _lineAngle?;
121
121
  private _crossHatch?;
122
122
  private _frequency?;
123
- private _pulseWidth?;
123
+ private _qPulseWidth?;
124
124
  constructor(init?: CutSettingInit);
125
125
  get type(): string;
126
126
  set type(value: string);
@@ -170,8 +170,8 @@ declare class CutSetting extends LightBurnBaseElement {
170
170
  set crossHatch(value: boolean | undefined);
171
171
  get frequency(): number | undefined;
172
172
  set frequency(value: number | undefined);
173
- get pulseWidth(): number | undefined;
174
- set pulseWidth(value: number | undefined);
173
+ get qPulseWidth(): number | undefined;
174
+ set qPulseWidth(value: number | undefined);
175
175
  getXmlAttributes(): Record<string, string | number | boolean | undefined>;
176
176
  getChildren(): LightBurnBaseElement[];
177
177
  static fromXmlJson(node: XmlJsonElement): CutSetting;
package/dist/index.js CHANGED
@@ -295,7 +295,7 @@ var CutSetting = class _CutSetting extends LightBurnBaseElement {
295
295
  _lineAngle;
296
296
  _crossHatch;
297
297
  _frequency;
298
- _pulseWidth;
298
+ _qPulseWidth;
299
299
  constructor(init) {
300
300
  super();
301
301
  this.token = "CutSetting";
@@ -326,7 +326,7 @@ var CutSetting = class _CutSetting extends LightBurnBaseElement {
326
326
  if (init.lineAngle !== void 0) this._lineAngle = init.lineAngle;
327
327
  if (init.crossHatch !== void 0) this._crossHatch = init.crossHatch;
328
328
  if (init.frequency !== void 0) this._frequency = init.frequency;
329
- if (init.pulseWidth !== void 0) this._pulseWidth = init.pulseWidth;
329
+ if (init.qPulseWidth !== void 0) this._qPulseWidth = init.qPulseWidth;
330
330
  }
331
331
  }
332
332
  get type() {
@@ -473,11 +473,11 @@ var CutSetting = class _CutSetting extends LightBurnBaseElement {
473
473
  set frequency(value) {
474
474
  this._frequency = value;
475
475
  }
476
- get pulseWidth() {
477
- return this._pulseWidth;
476
+ get qPulseWidth() {
477
+ return this._qPulseWidth;
478
478
  }
479
- set pulseWidth(value) {
480
- this._pulseWidth = value;
479
+ set qPulseWidth(value) {
480
+ this._qPulseWidth = value;
481
481
  }
482
482
  getXmlAttributes() {
483
483
  return {
@@ -510,7 +510,7 @@ var CutSetting = class _CutSetting extends LightBurnBaseElement {
510
510
  "lineAngle",
511
511
  "crossHatch",
512
512
  "frequency",
513
- "pulseWidth"
513
+ "qPulseWidth"
514
514
  ];
515
515
  for (const prop of props) {
516
516
  const value = this[`_${prop}`];
@@ -552,7 +552,7 @@ var CutSetting = class _CutSetting extends LightBurnBaseElement {
552
552
  cs.lineAngle = num(getChildValue("lineAngle"), void 0);
553
553
  cs.crossHatch = boolish(getChildValue("crossHatch"), void 0);
554
554
  cs.frequency = num(getChildValue("frequency"), void 0);
555
- cs.pulseWidth = num(getChildValue("pulseWidth"), void 0);
555
+ cs.qPulseWidth = num(getChildValue("QPulseWidth"), void 0);
556
556
  return cs;
557
557
  }
558
558
  };
@@ -579,7 +579,8 @@ var CutSettingPropertyElement = class extends LightBurnBaseElement {
579
579
  }
580
580
  toXml(indent = 0) {
581
581
  const indentStr = " ".repeat(indent);
582
- return `${indentStr}<${this.propName} Value="${this.formatValue(this.propValue)}"/>`;
582
+ const tagName = this.propName === "qPulseWidth" ? "QPulseWidth" : this.propName;
583
+ return `${indentStr}<${tagName} Value="${this.formatValue(this.propValue)}"/>`;
583
584
  }
584
585
  };
585
586
  LightBurnBaseElement.register("CutSetting", CutSetting);
@@ -1255,7 +1256,39 @@ LightBurnBaseElement.register("Shape.Bitmap", ShapeBitmap);
1255
1256
  import { stringify } from "svgson";
1256
1257
 
1257
1258
  // lib/svg-gen/assemble.ts
1258
- function assembleSvg(children, layout) {
1259
+ function assembleSvg(children, layout, defs) {
1260
+ const svgChildren = [];
1261
+ if (defs && defs.length > 0) {
1262
+ svgChildren.push({
1263
+ name: "defs",
1264
+ type: "element",
1265
+ value: "",
1266
+ attributes: {},
1267
+ children: defs
1268
+ });
1269
+ }
1270
+ svgChildren.push({
1271
+ name: "rect",
1272
+ type: "element",
1273
+ value: "",
1274
+ attributes: {
1275
+ x: String(layout.bg.x),
1276
+ y: String(layout.bg.y),
1277
+ width: String(layout.bg.width),
1278
+ height: String(layout.bg.height),
1279
+ fill: "white"
1280
+ },
1281
+ children: []
1282
+ });
1283
+ svgChildren.push({
1284
+ name: "g",
1285
+ type: "element",
1286
+ value: "",
1287
+ attributes: {
1288
+ transform: `matrix(1 0 0 -1 0 ${layout.flipY})`
1289
+ },
1290
+ children
1291
+ });
1259
1292
  return {
1260
1293
  name: "svg",
1261
1294
  type: "element",
@@ -1267,30 +1300,7 @@ function assembleSvg(children, layout) {
1267
1300
  viewBox: layout.viewBox,
1268
1301
  style: "background-color: white;"
1269
1302
  },
1270
- children: [
1271
- {
1272
- name: "rect",
1273
- type: "element",
1274
- value: "",
1275
- attributes: {
1276
- x: String(layout.bg.x),
1277
- y: String(layout.bg.y),
1278
- width: String(layout.bg.width),
1279
- height: String(layout.bg.height),
1280
- fill: "white"
1281
- },
1282
- children: []
1283
- },
1284
- {
1285
- name: "g",
1286
- type: "element",
1287
- value: "",
1288
- attributes: {
1289
- transform: `matrix(1 0 0 -1 0 ${layout.flipY})`
1290
- },
1291
- children
1292
- }
1293
- ]
1303
+ children: svgChildren
1294
1304
  };
1295
1305
  }
1296
1306
 
@@ -1334,6 +1344,104 @@ function collectCutSettings(root) {
1334
1344
  return settings;
1335
1345
  }
1336
1346
 
1347
+ // lib/svg-gen/node-helpers.ts
1348
+ var g = (attrs, children = []) => ({
1349
+ name: "g",
1350
+ type: "element",
1351
+ value: "",
1352
+ attributes: attrs,
1353
+ children
1354
+ });
1355
+ var leaf = (name, attrs) => ({
1356
+ name,
1357
+ type: "element",
1358
+ value: "",
1359
+ attributes: attrs,
1360
+ children: []
1361
+ });
1362
+ var textNode = (value) => ({
1363
+ name: "",
1364
+ type: "text",
1365
+ value,
1366
+ attributes: {},
1367
+ children: []
1368
+ });
1369
+
1370
+ // lib/svg-gen/fill-patterns.ts
1371
+ function generatePatternId(params) {
1372
+ const opacity = params.opacity ?? 0.8;
1373
+ const safeColor = encodeURIComponent(params.color).replace(
1374
+ /[^a-zA-Z0-9]/g,
1375
+ "_"
1376
+ );
1377
+ return `hatch-${params.interval.toFixed(4)}-${params.angleDeg}-${params.crossHatch}-${safeColor}-${params.strokeWidth.toFixed(4)}-${opacity.toFixed(2)}`;
1378
+ }
1379
+ function createHatchPattern(params) {
1380
+ const { interval, angleDeg, crossHatch, color, strokeWidth } = params;
1381
+ const opacity = params.opacity ?? 0.8;
1382
+ const id = generatePatternId(params);
1383
+ let d = `M ${-interval} 0 L ${interval} 0`;
1384
+ if (crossHatch) {
1385
+ d += ` M 0 ${-interval} L 0 ${interval}`;
1386
+ }
1387
+ return {
1388
+ name: "pattern",
1389
+ type: "element",
1390
+ value: "",
1391
+ attributes: {
1392
+ id,
1393
+ patternUnits: "userSpaceOnUse",
1394
+ width: String(interval),
1395
+ height: String(interval),
1396
+ patternTransform: `rotate(${angleDeg})`
1397
+ },
1398
+ children: [
1399
+ leaf("path", {
1400
+ d,
1401
+ stroke: color,
1402
+ "stroke-width": String(strokeWidth),
1403
+ "stroke-opacity": String(opacity)
1404
+ })
1405
+ ]
1406
+ };
1407
+ }
1408
+ var HatchPatternRegistry = class {
1409
+ patterns = /* @__PURE__ */ new Map();
1410
+ /**
1411
+ * Get or create a pattern for the given parameters.
1412
+ * @returns The pattern ID to use in fill="url(#id)"
1413
+ */
1414
+ getOrCreate(params) {
1415
+ const id = generatePatternId(params);
1416
+ if (!this.patterns.has(id)) {
1417
+ this.patterns.set(id, createHatchPattern(params));
1418
+ }
1419
+ return id;
1420
+ }
1421
+ /**
1422
+ * Get all registered patterns for the <defs> section.
1423
+ */
1424
+ getPatterns() {
1425
+ return Array.from(this.patterns.values());
1426
+ }
1427
+ /**
1428
+ * Check if any patterns have been registered.
1429
+ */
1430
+ hasPatterns() {
1431
+ return this.patterns.size > 0;
1432
+ }
1433
+ };
1434
+ function fillSettingsToPatternParams(settings, color, strokeWidth, opacity) {
1435
+ return {
1436
+ interval: settings.interval,
1437
+ angleDeg: settings.angle,
1438
+ crossHatch: settings.crossHatch,
1439
+ color,
1440
+ strokeWidth,
1441
+ opacity
1442
+ };
1443
+ }
1444
+
1337
1445
  // lib/svg-gen/options.ts
1338
1446
  var DEFAULT_OPTIONS = {
1339
1447
  margin: 10,
@@ -1415,29 +1523,6 @@ function addPts(bb, pts) {
1415
1523
  return bb;
1416
1524
  }
1417
1525
 
1418
- // lib/svg-gen/node-helpers.ts
1419
- var g = (attrs, children = []) => ({
1420
- name: "g",
1421
- type: "element",
1422
- value: "",
1423
- attributes: attrs,
1424
- children
1425
- });
1426
- var leaf = (name, attrs) => ({
1427
- name,
1428
- type: "element",
1429
- value: "",
1430
- attributes: attrs,
1431
- children: []
1432
- });
1433
- var textNode = (value) => ({
1434
- name: "",
1435
- type: "text",
1436
- value,
1437
- attributes: {},
1438
- children: []
1439
- });
1440
-
1441
1526
  // lib/svg-gen/registry/shape-bitmap.ts
1442
1527
  var bitmapRenderer = {
1443
1528
  match: (s) => s instanceof ShapeBitmap,
@@ -1474,124 +1559,6 @@ var bitmapRenderer = {
1474
1559
  }
1475
1560
  };
1476
1561
 
1477
- // lib/svg-gen/fill-patterns.ts
1478
- function generateScanLines(bbox, settings, color, strokeWidth) {
1479
- const lines = [];
1480
- const angleRad = settings.angle * Math.PI / 180;
1481
- const primaryLines = generateLinesAtAngle(
1482
- bbox,
1483
- settings.interval,
1484
- angleRad,
1485
- color,
1486
- strokeWidth
1487
- );
1488
- lines.push(...primaryLines);
1489
- if (settings.crossHatch) {
1490
- const perpAngle = angleRad + Math.PI / 2;
1491
- const crossLines = generateLinesAtAngle(
1492
- bbox,
1493
- settings.interval,
1494
- perpAngle,
1495
- color,
1496
- strokeWidth
1497
- );
1498
- lines.push(...crossLines);
1499
- }
1500
- return lines;
1501
- }
1502
- function generateLinesAtAngle(bbox, interval, angle, color, strokeWidth) {
1503
- const lines = [];
1504
- const diagonal = Math.sqrt(
1505
- Math.pow(bbox.maxX - bbox.minX, 2) + Math.pow(bbox.maxY - bbox.minY, 2)
1506
- );
1507
- const dx = Math.cos(angle);
1508
- const dy = Math.sin(angle);
1509
- const px = -Math.sin(angle);
1510
- const py = Math.cos(angle);
1511
- const cx = (bbox.minX + bbox.maxX) / 2;
1512
- const cy = (bbox.minY + bbox.maxY) / 2;
1513
- const numLines = Math.ceil(diagonal / interval) + 2;
1514
- for (let i = -numLines / 2; i <= numLines / 2; i++) {
1515
- const offset = i * interval;
1516
- const startX = cx + px * offset - dx * diagonal;
1517
- const startY = cy + py * offset - dy * diagonal;
1518
- const endX = cx + px * offset + dx * diagonal;
1519
- const endY = cy + py * offset + dy * diagonal;
1520
- const clipped = clipLineToBBox(
1521
- startX,
1522
- startY,
1523
- endX,
1524
- endY,
1525
- bbox.minX,
1526
- bbox.minY,
1527
- bbox.maxX,
1528
- bbox.maxY
1529
- );
1530
- if (clipped) {
1531
- lines.push(
1532
- leaf("line", {
1533
- x1: String(clipped.x1),
1534
- y1: String(clipped.y1),
1535
- x2: String(clipped.x2),
1536
- y2: String(clipped.y2),
1537
- stroke: color,
1538
- "stroke-width": String(strokeWidth),
1539
- "stroke-opacity": "0.8"
1540
- })
1541
- );
1542
- }
1543
- }
1544
- return lines;
1545
- }
1546
- function clipLineToBBox(x1, y1, x2, y2, minX, minY, maxX, maxY) {
1547
- const INSIDE = 0;
1548
- const LEFT = 1;
1549
- const RIGHT = 2;
1550
- const BOTTOM = 4;
1551
- const TOP = 8;
1552
- function computeOutCode(x, y) {
1553
- let code = INSIDE;
1554
- if (x < minX) code |= LEFT;
1555
- else if (x > maxX) code |= RIGHT;
1556
- if (y < minY) code |= BOTTOM;
1557
- else if (y > maxY) code |= TOP;
1558
- return code;
1559
- }
1560
- let outcode1 = computeOutCode(x1, y1);
1561
- let outcode2 = computeOutCode(x2, y2);
1562
- while (true) {
1563
- if (!(outcode1 | outcode2)) {
1564
- return { x1, y1, x2, y2 };
1565
- } else if (outcode1 & outcode2) {
1566
- return null;
1567
- }
1568
- const outcodeOut = outcode1 ? outcode1 : outcode2;
1569
- let x, y;
1570
- if (outcodeOut & TOP) {
1571
- x = x1 + (x2 - x1) * (maxY - y1) / (y2 - y1);
1572
- y = maxY;
1573
- } else if (outcodeOut & BOTTOM) {
1574
- x = x1 + (x2 - x1) * (minY - y1) / (y2 - y1);
1575
- y = minY;
1576
- } else if (outcodeOut & RIGHT) {
1577
- y = y1 + (y2 - y1) * (maxX - x1) / (x2 - x1);
1578
- x = maxX;
1579
- } else {
1580
- y = y1 + (y2 - y1) * (minX - x1) / (x2 - x1);
1581
- x = minX;
1582
- }
1583
- if (outcodeOut === outcode1) {
1584
- x1 = x;
1585
- y1 = y;
1586
- outcode1 = computeOutCode(x1, y1);
1587
- } else {
1588
- x2 = x;
1589
- y2 = y;
1590
- outcode2 = computeOutCode(x2, y2);
1591
- }
1592
- }
1593
- }
1594
-
1595
1562
  // lib/svg-gen/palette.ts
1596
1563
  var LIGHTBURN_COLORS = {
1597
1564
  0: "#000000",
@@ -1678,26 +1645,31 @@ var ellipseRenderer = {
1678
1645
  const cutSetting = el.cutIndex !== void 0 ? cutSettings.get(el.cutIndex) : void 0;
1679
1646
  const shouldShowFill = cutSetting && (cutSetting.type === "Scan" || cutSetting.type === "Scan+Cut");
1680
1647
  if (shouldShowFill && cutSetting) {
1681
- const localBBox = {
1682
- minX: -rx,
1683
- minY: -ry,
1684
- maxX: rx,
1685
- maxY: ry
1686
- };
1687
1648
  const fillSettings = {
1688
1649
  interval: cutSetting.interval || 0.1,
1689
1650
  angle: cutSetting.angle || 0,
1690
1651
  crossHatch: cutSetting.crossHatch || false
1691
1652
  };
1692
- const fillLines = generateScanLines(
1693
- localBBox,
1694
- fillSettings,
1695
- stroke,
1696
- options.strokeWidth
1653
+ const patternId = options.patternRegistry.getOrCreate(
1654
+ fillSettingsToPatternParams(fillSettings, stroke, options.strokeWidth)
1697
1655
  );
1698
- children.push(...fillLines);
1656
+ const fillChild = rx === ry ? leaf("circle", {
1657
+ cx: "0",
1658
+ cy: "0",
1659
+ r: String(rx),
1660
+ fill: `url(#${patternId})`,
1661
+ stroke: "none"
1662
+ }) : leaf("ellipse", {
1663
+ cx: "0",
1664
+ cy: "0",
1665
+ rx: String(rx),
1666
+ ry: String(ry),
1667
+ fill: `url(#${patternId})`,
1668
+ stroke: "none"
1669
+ });
1670
+ children.push(fillChild);
1699
1671
  }
1700
- const child = rx === ry ? leaf("circle", {
1672
+ const outlineChild = rx === ry ? leaf("circle", {
1701
1673
  cx: "0",
1702
1674
  cy: "0",
1703
1675
  r: String(rx),
@@ -1711,7 +1683,7 @@ var ellipseRenderer = {
1711
1683
  fill: "none",
1712
1684
  stroke
1713
1685
  });
1714
- children.push(child);
1686
+ children.push(outlineChild);
1715
1687
  return g({ transform }, children);
1716
1688
  }
1717
1689
  };
@@ -1931,44 +1903,26 @@ var groupRenderer = {
1931
1903
  const cutSetting = cutIndex !== void 0 ? cutSettings.get(cutIndex) : void 0;
1932
1904
  const shouldShowFill = cutSetting && (cutSetting.type === "Scan" || cutSetting.type === "Scan+Cut");
1933
1905
  if (shouldShowFill && cutSetting) {
1934
- const bbox = shapeChildren.reduce(
1935
- (bb, c) => boxUnion(bb, bboxOfShape(c)),
1936
- emptyBox()
1937
- );
1938
1906
  const fillSettings = {
1939
1907
  interval: cutSetting.interval || 0.1,
1940
1908
  angle: cutSetting.angle || 0,
1941
1909
  crossHatch: cutSetting.crossHatch || false
1942
1910
  };
1943
- const fillLines = generateScanLines(
1944
- bbox,
1945
- fillSettings,
1946
- stroke,
1947
- options.strokeWidth
1911
+ const patternId = options.patternRegistry.getOrCreate(
1912
+ fillSettingsToPatternParams(
1913
+ fillSettings,
1914
+ stroke,
1915
+ options.strokeWidth
1916
+ )
1917
+ );
1918
+ children2.push(
1919
+ leaf("path", {
1920
+ d: combinedPathData,
1921
+ fill: `url(#${patternId})`,
1922
+ "fill-rule": "nonzero",
1923
+ stroke: "none"
1924
+ })
1948
1925
  );
1949
- const clipId = `clip-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
1950
- const clipPath = {
1951
- name: "clipPath",
1952
- type: "element",
1953
- value: "",
1954
- attributes: { id: clipId },
1955
- children: [
1956
- leaf("path", {
1957
- d: combinedPathData,
1958
- "fill-rule": "nonzero",
1959
- "clip-rule": "nonzero"
1960
- })
1961
- ]
1962
- };
1963
- const clippedGroup = {
1964
- name: "g",
1965
- type: "element",
1966
- value: "",
1967
- attributes: { "clip-path": `url(#${clipId})` },
1968
- children: fillLines
1969
- };
1970
- children2.push(clipPath);
1971
- children2.push(clippedGroup);
1972
1926
  }
1973
1927
  children2.push(
1974
1928
  leaf("path", {
@@ -2026,38 +1980,22 @@ var pathRenderer = {
2026
1980
  const cutSetting = p.cutIndex !== void 0 ? cutSettings.get(p.cutIndex) : void 0;
2027
1981
  const shouldShowFill = p.isClosed && cutSetting && (cutSetting.type === "Scan" || cutSetting.type === "Scan+Cut");
2028
1982
  if (shouldShowFill && cutSetting) {
2029
- const bbox = addPts(
2030
- emptyBox(),
2031
- p.verts.map((v) => ({ x: v.x, y: v.y }))
2032
- );
2033
1983
  const fillSettings = {
2034
1984
  interval: cutSetting.interval || 0.1,
2035
1985
  angle: cutSetting.angle || 0,
2036
1986
  crossHatch: cutSetting.crossHatch || false
2037
1987
  };
2038
- const fillLines = generateScanLines(
2039
- bbox,
2040
- fillSettings,
2041
- stroke,
2042
- options.strokeWidth
1988
+ const patternId = options.patternRegistry.getOrCreate(
1989
+ fillSettingsToPatternParams(fillSettings, stroke, options.strokeWidth)
1990
+ );
1991
+ children.push(
1992
+ leaf("path", {
1993
+ d,
1994
+ fill: `url(#${patternId})`,
1995
+ "fill-rule": "nonzero",
1996
+ stroke: "none"
1997
+ })
2043
1998
  );
2044
- const clipId = `clip-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
2045
- const clipPath = {
2046
- name: "clipPath",
2047
- type: "element",
2048
- value: "",
2049
- attributes: { id: clipId },
2050
- children: [leaf("path", { d })]
2051
- };
2052
- const clippedGroup = {
2053
- name: "g",
2054
- type: "element",
2055
- value: "",
2056
- attributes: { "clip-path": `url(#${clipId})` },
2057
- children: fillLines
2058
- };
2059
- children.push(clipPath);
2060
- children.push(clippedGroup);
2061
1999
  }
2062
2000
  children.push(
2063
2001
  leaf("path", {
@@ -2102,24 +2040,26 @@ var rectRenderer = {
2102
2040
  const cutSetting = rect.cutIndex !== void 0 ? cutSettings.get(rect.cutIndex) : void 0;
2103
2041
  const shouldShowFill = cutSetting && (cutSetting.type === "Scan" || cutSetting.type === "Scan+Cut");
2104
2042
  if (shouldShowFill && cutSetting) {
2105
- const localBBox = {
2106
- minX: 0,
2107
- minY: 0,
2108
- maxX: w,
2109
- maxY: h
2110
- };
2111
2043
  const fillSettings = {
2112
2044
  interval: cutSetting.interval || 0.1,
2113
2045
  angle: cutSetting.angle || 0,
2114
2046
  crossHatch: cutSetting.crossHatch || false
2115
2047
  };
2116
- const fillLines = generateScanLines(
2117
- localBBox,
2118
- fillSettings,
2119
- stroke,
2120
- options.strokeWidth
2048
+ const patternId = options.patternRegistry.getOrCreate(
2049
+ fillSettingsToPatternParams(fillSettings, stroke, options.strokeWidth)
2050
+ );
2051
+ children.push(
2052
+ leaf("rect", {
2053
+ x: "0",
2054
+ y: "0",
2055
+ width: String(w),
2056
+ height: String(h),
2057
+ rx: String(cr),
2058
+ ry: String(cr),
2059
+ fill: `url(#${patternId})`,
2060
+ stroke: "none"
2061
+ })
2121
2062
  );
2122
- children.push(...fillLines);
2123
2063
  }
2124
2064
  children.push(
2125
2065
  leaf("rect", {
@@ -2193,11 +2133,8 @@ function svgForShape(shape, cutSettings, options) {
2193
2133
  function measure(shapes) {
2194
2134
  return shapes.reduce((acc, s) => boxUnion(acc, bboxOfShape(s)), emptyBox());
2195
2135
  }
2196
- function renderAll(shapes, cutSettings, svgOptions) {
2197
- const renderOptions = {
2198
- strokeWidth: svgOptions?.defaultStrokeWidth ?? DEFAULT_OPTIONS.defaultStrokeWidth
2199
- };
2200
- return shapes.map((s) => svgForShape(s, cutSettings, renderOptions));
2136
+ function renderAll(shapes, cutSettings, options) {
2137
+ return shapes.map((s) => svgForShape(s, cutSettings, options));
2201
2138
  }
2202
2139
 
2203
2140
  // lib/svg-gen/index.ts
@@ -2206,8 +2143,14 @@ function generateLightBurnSvg(root, options) {
2206
2143
  const cutSettings = collectCutSettings(root);
2207
2144
  const bbox = measure(shapes);
2208
2145
  const layout = computeLayout(bbox, options);
2209
- const nodes = renderAll(shapes, cutSettings, options);
2210
- const svgTree = assembleSvg(nodes, layout);
2146
+ const patternRegistry = new HatchPatternRegistry();
2147
+ const renderOptions = {
2148
+ strokeWidth: options?.defaultStrokeWidth ?? DEFAULT_OPTIONS.defaultStrokeWidth,
2149
+ patternRegistry
2150
+ };
2151
+ const nodes = renderAll(shapes, cutSettings, renderOptions);
2152
+ const defs = patternRegistry.getPatterns();
2153
+ const svgTree = assembleSvg(nodes, layout, defs);
2211
2154
  return stringify(svgTree);
2212
2155
  }
2213
2156
  export {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "lbrnts",
3
3
  "main": "dist/index.js",
4
4
  "type": "module",
5
- "version": "0.0.15",
5
+ "version": "0.0.17",
6
6
  "files": [
7
7
  "dist"
8
8
  ],