circuitscript 0.0.13 → 0.0.15

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.
@@ -1,6 +1,6 @@
1
1
  import { G } from "@svgdotjs/svg.js";
2
2
 
3
- import { SymbolPinSide, bodyColor, defaultFont } from "./globals.js";
3
+ import { SymbolPinSide, bodyColor, defaultFontBold, defaultFont } from "./globals.js";
4
4
  import { Feature, Geometry, GeometryProp, HorizontalAlign, Label, LabelStyle, VerticalAlign } from "./geometry.js";
5
5
  import { Logger } from "./logger.js";
6
6
 
@@ -154,6 +154,7 @@ export abstract class SymbolGraphic {
154
154
  anchor = HorizontalAlign.Left,
155
155
  vanchor = VerticalAlign.Bottom,
156
156
  fontWeight = 'regular',
157
+ angle: labelAngle = 0,
157
158
  } = tmpLabel.style ?? {};
158
159
 
159
160
  let anchorStyle = 'start';
@@ -196,28 +197,38 @@ export abstract class SymbolGraphic {
196
197
  }
197
198
 
198
199
  const position = tmpLabel.getLabelPosition();
200
+ const useFont = defaultFont;
199
201
 
200
- let useFont = defaultFont;
201
- if (fontWeight === 'bold'){
202
- useFont = 'Inter-Bold';
203
- }
204
-
205
- const text = group.text(tmpLabel.text)
202
+ const textContainer = group.group();
203
+ const text = textContainer.text(tmpLabel.text)
206
204
  .fill('#333')
207
205
  .font({
208
206
  family: useFont,
209
207
  size: fontSize,
210
208
  anchor: anchorStyle,
211
209
  'dominant-baseline': dominantBaseline,
212
- // weight: fontWeight,
210
+ weight: fontWeight,
213
211
  });
214
212
 
213
+ let translateX: number, translateY: number;
214
+ let useRotateAngle = 0;
215
+
215
216
  if (isRotation180){
216
- text.translate(-position[0], position[1]);
217
+ translateX = -position[0];
218
+ translateY = position[1];
219
+ useRotateAngle = 0;
217
220
  } else {
218
- text.translate(position[0], position[1])
219
- .rotate(this.angle, -position[0], -position[1]);
221
+ translateX = position[0];
222
+ translateY = position[1];
223
+ useRotateAngle = this.angle;
220
224
  }
225
+
226
+ text.rotate(labelAngle);
227
+ textContainer.translate(translateX, translateY)
228
+ .rotate(useRotateAngle, -translateX, -translateY);
229
+
230
+ // For debug, show the origin of the text container
231
+ // textContainer.circle(2).fill('red');
221
232
  });
222
233
  }
223
234
 
@@ -293,73 +304,233 @@ export class SymbolPlaceholder extends SymbolGraphic {
293
304
  drawing.angle = this._angle;
294
305
  const commands = drawing.getCommands();
295
306
 
296
- drawing.log(drawing.id, 'angle: ', this._angle, "commands:", commands.length);
307
+ drawing.log('id: ', drawing.id, 'angle: ', this._angle, "commands:", commands.length);
297
308
 
298
309
  commands.forEach(([commandName, positionParams, keywordParams]) => {
299
- if (commandName === 'rect') {
300
- drawing.log('add rect', ...positionParams);
301
- drawing.addRect(...positionParams);
302
-
303
- } else if (commandName === 'pin') {
304
- drawing.log('add pin', ...positionParams);
305
- drawing.addPin(...positionParams);
306
-
307
- } else if (commandName === 'hline') {
308
- drawing.log('add hline', ...positionParams);
309
- drawing.addHLine(...positionParams);
310
-
311
- } else if (commandName === 'vline') {
312
- drawing.log('add vline', ...positionParams);
313
- drawing.addVLine(...positionParams);
314
-
315
- } else if (commandName === 'line') {
316
- drawing.log('add line', ...positionParams);
317
- drawing.addLine(...positionParams);
318
-
319
- } else if (commandName === 'label') {
320
- const keywords = ['fontSize', 'anchor', 'vanchor'];
321
-
322
- // Create the style object
323
- const style = {};
324
- keywords.forEach(item => {
325
- if (keywordParams.has(item)){
326
- style[item] = keywordParams.get(item);
327
- }
328
- });
310
+ switch (commandName) {
311
+ case PlaceHolderCommands.rect:
312
+ drawing.log('add rect', ...positionParams);
313
+ drawing.addRect(...positionParams);
314
+ break;
329
315
 
330
- positionParams = [...positionParams];
331
- positionParams.push(style);
316
+ case PlaceHolderCommands.hline:
317
+ drawing.log('add hline', ...positionParams);
318
+ drawing.addHLine(...positionParams);
319
+ break;
332
320
 
333
- const labelId = positionParams[0];
321
+ case PlaceHolderCommands.vline:
322
+ drawing.log('add vline', ...positionParams);
323
+ drawing.addVLine(...positionParams);
324
+ break;
334
325
 
335
- const tmpPositionParams = [...positionParams];
336
- tmpPositionParams[3] = this.getLabelValue(labelId);
326
+ case PlaceHolderCommands.line:
327
+ drawing.log('add line', ...positionParams);
328
+ drawing.addLine(...positionParams);
329
+ break;
337
330
 
338
- drawing.log('add label', JSON.stringify(tmpPositionParams));
339
- drawing.addLabelId(...tmpPositionParams);
340
-
341
- } else if (commandName === 'path') {
342
- drawing.addPath(...positionParams);
343
- } else if (commandName === 'lineWidth') {
344
- drawing.addSetLineWidth(...positionParams);
345
- } else if (commandName === 'fill') {
346
- drawing.addSetFillColor(...positionParams);
347
- } else if (commandName === 'lineColor') {
348
- drawing.addSetLineColor(...positionParams);
349
- } else if (commandName === 'arc'){
350
- drawing.addArc(...positionParams);
331
+ case PlaceHolderCommands.path:
332
+ drawing.addPath(...positionParams);
333
+ break;
334
+
335
+ case PlaceHolderCommands.lineWidth:
336
+ drawing.addSetLineWidth(...positionParams);
337
+ break;
338
+
339
+ case PlaceHolderCommands.fill:
340
+ drawing.addSetFillColor(...positionParams);
341
+ break;
342
+
343
+ case PlaceHolderCommands.lineColor:
344
+ drawing.addSetLineColor(...positionParams);
345
+ break;
346
+
347
+ case PlaceHolderCommands.arc:
348
+ drawing.addArc(...positionParams);
349
+ break;
350
+
351
+ case PlaceHolderCommands.circle:
352
+ // circle params: center x, center y, radius
353
+ drawing.addArc(...positionParams, 0, 360);
354
+ break;
355
+
356
+ case PlaceHolderCommands.triangle:
357
+ drawing.addTriangle(...positionParams);
358
+ break;
359
+
360
+ case PlaceHolderCommands.pin:
361
+ case PlaceHolderCommands.hpin:
362
+ case PlaceHolderCommands.vpin:
363
+ {
364
+ this.drawPinParams(drawing, commandName,
365
+ keywordParams, positionParams);
366
+ break;
367
+ }
368
+
369
+ case PlaceHolderCommands.label: {
370
+ const keywords = ['fontSize', 'anchor', 'vanchor', 'angle'];
371
+
372
+ // Create the style object
373
+ const style = {};
374
+ keywords.forEach(item => {
375
+ if (keywordParams.has(item)) {
376
+ style[item] = keywordParams.get(item);
377
+ }
378
+ });
379
+
380
+ positionParams = [...positionParams];
381
+ positionParams.push(style);
382
+
383
+ const labelId = positionParams[0];
384
+
385
+ const tmpPositionParams = [...positionParams];
386
+
387
+ const tmpLabelValue = this.getLabelValue(labelId);
388
+ if (tmpLabelValue !== undefined) {
389
+ tmpPositionParams[3] = tmpLabelValue;
390
+ }
391
+
392
+ drawing.log('add label', JSON.stringify(tmpPositionParams));
393
+ drawing.addLabelId(...tmpPositionParams);
394
+ break;
395
+ }
351
396
  }
352
397
  });
353
398
 
354
399
  drawing.log("=== end generate drawing ===");
355
400
  }
356
401
 
402
+ drawPinParams(drawing: SymbolDrawingCommands,
403
+ commandName: string, keywordParams: Map<string, any>,
404
+ positionParams: any[]): void {
405
+
406
+ drawing.log('add pin', ...positionParams);
407
+
408
+ const keywordDisplayPinId = 'display_pin_id';
409
+ let displayPinId = true;
410
+
411
+ if (keywordParams.has(keywordDisplayPinId)) {
412
+ if (keywordParams.get(keywordDisplayPinId) === 0) {
413
+ displayPinId = false;
414
+ }
415
+ }
416
+
417
+ let pinNameParam: string | null = null;
418
+ if (typeof positionParams[1] === 'string') {
419
+ // If the type of the second position is a string, then
420
+ // use the string value as the pin name
421
+ pinNameParam = positionParams[1];
422
+ positionParams = [positionParams[0], ...positionParams.slice(2)];
423
+ }
424
+
425
+ // create the next point
426
+ const startX = positionParams[1];
427
+ const startY = positionParams[2];
428
+
429
+ if (commandName === PlaceHolderCommands.vpin) {
430
+ const magnitude = positionParams[3];
431
+ positionParams = [
432
+ positionParams[0],
433
+ startX,
434
+ startY,
435
+ startX,
436
+ startY + magnitude
437
+ ];
438
+ } else if (commandName === PlaceHolderCommands.hpin) {
439
+ const magnitude = positionParams[3];
440
+ positionParams = [
441
+ positionParams[0],
442
+ startX,
443
+ startY,
444
+ startX + magnitude,
445
+ startY
446
+ ];
447
+ }
448
+
449
+ drawing.addPin(...positionParams);
450
+
451
+ // Add a label for the pinId and pinName
452
+ const latestPin = this.drawing.pins[this.drawing.pins.length - 1];
453
+ const [pinId, , angle] = latestPin;
454
+ const [, , , endX, endY] = positionParams;
455
+
456
+ let pinNameAlignment = HorizontalAlign.Left;
457
+ let pinNameOffsetX = 4;
458
+
459
+ let pinIdOffsetX = 0;
460
+ let pinIdAlignment = HorizontalAlign.Left;
461
+
462
+ let pinIdVAlignment = VerticalAlign.Bottom;
463
+ let pinIdOffsetY = -2;
464
+
465
+ switch (angle) {
466
+ case 0:
467
+ pinNameAlignment = HorizontalAlign.Left;
468
+ pinNameOffsetX = 4;
469
+ pinIdAlignment = HorizontalAlign.Right;
470
+ pinIdOffsetX = -2;
471
+ break;
472
+ case 90:
473
+ case 180:
474
+ pinNameAlignment = HorizontalAlign.Right;
475
+ pinNameOffsetX = -4;
476
+ pinIdAlignment = HorizontalAlign.Left;
477
+ pinIdOffsetX = 2;
478
+ break;
479
+ case 270:
480
+ pinNameAlignment = HorizontalAlign.Left;
481
+ pinNameOffsetX = 4;
482
+ pinIdAlignment = HorizontalAlign.Left;
483
+ pinIdOffsetX = 2;
484
+ pinIdOffsetY = 2;
485
+ pinIdVAlignment = VerticalAlign.Top;
486
+ break;
487
+ }
488
+
489
+ if (angle === 0 || angle === 90 || angle === 180 || angle === 270) {
490
+ const usePinName = pinNameParam ?? "";
491
+
492
+ // Draw the pinName
493
+ usePinName !== "" && drawing.addLabel(
494
+ endX + pinNameOffsetX, endY, usePinName, {
495
+ fontSize: 10,
496
+ anchor: pinNameAlignment,
497
+ vanchor: VerticalAlign.Middle,
498
+ });
499
+
500
+ // Draw pin Id
501
+ displayPinId && drawing.addLabel(
502
+ endX + pinIdOffsetX, endY + pinIdOffsetY, pinId.toString(), {
503
+ fontSize: 8,
504
+ anchor: pinIdAlignment,
505
+ vanchor: pinIdVAlignment,
506
+ });
507
+ }
508
+ }
509
+
357
510
  constructor(drawing: SymbolDrawing) {
358
511
  super();
359
512
  this.drawing = drawing;
360
513
  }
361
514
  }
362
515
 
516
+ export enum PlaceHolderCommands {
517
+ arc = 'arc',
518
+ circle = 'circle',
519
+ rect = 'rect',
520
+ triangle = 'triangle',
521
+ pin = 'pin',
522
+ hpin = 'hpin',
523
+ vpin = 'vpin',
524
+ hline = 'hline',
525
+ vline = 'vline',
526
+ line = 'line',
527
+ label = 'label',
528
+ path = 'path',
529
+ lineWidth = 'lineWidth',
530
+ fill = 'fill',
531
+ lineColor = 'lineColor'
532
+ }
533
+
363
534
  export class SymbolCustom extends SymbolGraphic {
364
535
 
365
536
  pinDefinition: SymbolPinDefintion[] = [];
@@ -407,7 +578,7 @@ export class SymbolCustom extends SymbolGraphic {
407
578
  const bodyWidth = this.bodyWidth;
408
579
  const bodyHeight = (1 + Math.max(maxLeftPins, maxRightPins)) * this.pinSpacing;
409
580
 
410
- drawing.addSetFillColor(bodyColor);
581
+ // drawing.addSetFillColor(bodyColor);
411
582
 
412
583
  drawing.addRect(0, 0, bodyWidth, bodyHeight);
413
584
 
@@ -455,18 +626,23 @@ export class SymbolCustom extends SymbolGraphic {
455
626
  });
456
627
 
457
628
  const instanceName = this.getLabelValue("refdes");
458
- const MPN = this.getLabelValue("MPN");
459
-
460
629
  instanceName && drawing.addLabel(-bodyWidth/2, -bodyHeight/2 - 4, instanceName, {
461
630
  fontSize: 10,
462
631
  anchor: HorizontalAlign.Left,
463
632
  });
464
633
 
465
- MPN && drawing.addLabel(-bodyWidth/2, bodyHeight/2 + 4, MPN, {
466
- fontSize: 10,
467
- anchor: HorizontalAlign.Left,
468
- vanchor: VerticalAlign.Top,
469
- });
634
+ const acceptedMPNKeys = ['MPN', 'mpn', 'manufacturer_pn'];
635
+
636
+ acceptedMPNKeys.some(key => {
637
+ const labelValue = this.getLabelValue(key);
638
+ if (labelValue !== undefined){
639
+ drawing.addLabel(-bodyWidth/2, bodyHeight/2 + 4, labelValue, {
640
+ fontSize: 10,
641
+ anchor: HorizontalAlign.Left,
642
+ vanchor: VerticalAlign.Top,
643
+ });
644
+ }
645
+ });
470
646
 
471
647
  this.drawing = drawing;
472
648
  this._cacheLeftPins = leftPins;
@@ -516,10 +692,13 @@ export class SymbolDrawing {
516
692
  addPin(pinId: number, startX: number, startY: number,
517
693
  endX: number, endY: number): SymbolDrawing {
518
694
 
519
- // Determine the pin angle based on the start and end values.
695
+ // Determine the pin angle based on vector with start point
696
+ // going to end point. The angle is relative to the x-axis.
697
+ // 270
698
+ // 180 -- start --> 0
699
+ // 90
520
700
 
521
701
  let angle = 0;
522
-
523
702
  if (startX === endX) {
524
703
  if (startY > endY) {
525
704
  angle = 270;
@@ -574,6 +753,29 @@ export class SymbolDrawing {
574
753
  return this;
575
754
  }
576
755
 
756
+ addTriangle(startX: number, startY: number, endX: number, endY: number, width: number): SymbolDrawing {
757
+ const line = Geometry.line(
758
+ startX, startY,
759
+ endX, endY);
760
+
761
+ const normLine = line.norm;
762
+ const dx1 = normLine.x * width / 2;
763
+ const dy1 = normLine.y * width / 2;
764
+ const dx2 = normLine.x * -width / 2;
765
+ const dy2 = normLine.y * -width / 2;
766
+
767
+ this.items.push(
768
+ Geometry.polygon([
769
+ [dx1 + startX, dy1 + startY],
770
+ [dx2 + startX, dy2 + startY],
771
+ [endX, endY],
772
+ [dx1 + startX, dy1 + startY],
773
+ ])
774
+ );
775
+
776
+ return this;
777
+ }
778
+
577
779
  addRect2(x: number, y: number, x2: number, y2: number): SymbolDrawing {
578
780
  this.items.push(
579
781
  Geometry.polygon([
@@ -824,7 +1026,7 @@ export class SymbolDrawingCommands extends SymbolDrawing {
824
1026
  clone(): SymbolDrawingCommands {
825
1027
  // Force a deep clone
826
1028
  const tmpCommands: SubExpressionCommand[] = this.commands.map(item => {
827
- if (item[0] === "label") {
1029
+ if (item[0] === PlaceHolderCommands.label) {
828
1030
  const commandName = item[0];
829
1031
  const positionParams = item[1];
830
1032
  const keywordParams = item[2];
package/src/geometry.ts CHANGED
@@ -2,10 +2,12 @@ import Flatten from '@flatten-js/core'
2
2
  import { measureTextSize2 } from './sizing.js';
3
3
  import { defaultFont } from './globals.js';
4
4
  import { Box } from '@svgdotjs/svg.js';
5
+ import { NumericValue } from './objects/ParamDefinition.js';
5
6
 
6
7
  export type Segment = Flatten.Segment;
7
8
  export type Polygon = Flatten.Polygon;
8
9
  export type Multiline = Flatten.Multiline;
10
+ export type Line = Flatten.Line;
9
11
 
10
12
  export type Arc = Flatten.Arc;
11
13
 
@@ -15,6 +17,7 @@ export type LabelStyle = {
15
17
  font?: string,
16
18
  fontSize?: number,
17
19
  fontWeight?: string,
20
+ angle?: number,
18
21
 
19
22
  anchor?: HorizontalAlign.Left | HorizontalAlign.Middle | HorizontalAlign.Right, // Horizontal anchor
20
23
  vanchor?: VerticalAlign.Top | VerticalAlign.Middle | VerticalAlign.Bottom, // Vertical anchor
@@ -62,15 +65,28 @@ export class Label extends Flatten.Polygon {
62
65
  static fromPoint(id: string, x: number, y: number,
63
66
  text: string, style: LabelStyle): Label {
64
67
 
68
+ let useText: string;
69
+ if (typeof text === 'number'){
70
+ useText = (text as number).toString();
71
+ } else if (typeof text === 'object'
72
+ && text instanceof NumericValue) {
73
+ useText = (text as NumericValue).toDisplayString();
74
+ } else if (typeof text === 'string'){
75
+ useText = text;
76
+ } else {
77
+ throw 'Invalid string passed into label';
78
+ }
79
+
65
80
  const { fontSize = 10,
66
81
  anchor = HorizontalAlign.Left,
67
82
  vanchor = VerticalAlign.Bottom,
68
83
  fontWeight = 'regular',
69
84
  } = style ?? {};
70
85
 
71
- // Determine the size of the text
86
+ // Determine the size of the text, this is needed to determine the
87
+ // bounding box of the text for layout purposes.
72
88
  const { width, height, box } =
73
- measureTextSize2(text, defaultFont, fontSize, fontWeight,
89
+ measureTextSize2(useText, defaultFont, fontSize, fontWeight,
74
90
  anchor, vanchor);
75
91
 
76
92
  // const polygonCoords =
@@ -87,7 +103,7 @@ export class Label extends Flatten.Polygon {
87
103
  const polygon = new Flatten.Polygon(polygonCoords);
88
104
 
89
105
  // Create the bounds of the label
90
- return new Label(id, text, [x, y], polygon, style, box);
106
+ return new Label(id, useText, [x, y], polygon, style, box);
91
107
  }
92
108
 
93
109
  rotate(angle: number, origin: Flatten.Point): Label {
@@ -116,6 +132,13 @@ export class Geometry {
116
132
  return new Flatten.Point(x, y);
117
133
  }
118
134
 
135
+ static line(x1: number, y1: number, x2: number, y2: number): Flatten.Line {
136
+ return new Flatten.Line(
137
+ Geometry.point(x1, y1),
138
+ Geometry.point(x2, y2)
139
+ )
140
+ }
141
+
119
142
  static label(id: string, x: number, y: number, text: string, style: LabelStyle): Label {
120
143
  return Label.fromPoint(id, x, y, text, style);
121
144
  }
@@ -187,7 +210,14 @@ export class Geometry {
187
210
 
188
211
  features.forEach(feature => {
189
212
  const box = feature.box;
190
- if (box.xmin === undefined){
213
+
214
+ if (feature instanceof Label
215
+ && typeof feature.text === 'string'
216
+ && feature.text.trim().length === 0) {
217
+ return;
218
+ }
219
+
220
+ if (box.xmin === undefined) {
191
221
  throw "Invalid box!";
192
222
  }
193
223
 
@@ -218,6 +248,8 @@ export class Geometry {
218
248
  console.log('unknown type', feature);
219
249
  }
220
250
 
251
+ static FullCircleRadians = 2 * Math.PI;
252
+
221
253
  static featuresToPath(items: Feature[]):
222
254
  { path: string, isClosedPolygon: boolean } {
223
255
 
@@ -237,16 +269,26 @@ export class Geometry {
237
269
  const y = item.center.y;
238
270
  const radius = item.r as number;
239
271
 
272
+ let useEndAngle = item.endAngle;
273
+ let extraEnd = '';
274
+ if (item.startAngle === 0 && item.endAngle === Geometry.FullCircleRadians){
275
+ // detect as a circle and close the polygon
276
+ useEndAngle = 359.9999 * Math.PI/ 180;
277
+ isClosedPolygon = true;
278
+ extraEnd = ' Z'; // close the circle
279
+ }
280
+
240
281
  // Assume angle is clockwise for now
241
282
  const startPoint = getArcPointRadians(x, y, radius,
242
283
  item.startAngle);
243
284
 
244
285
  const endPoint = getArcPointRadians(x, y, radius,
245
- item.endAngle);
286
+ useEndAngle);
246
287
 
247
288
  paths.push('M ' + startPoint[0] + ' ' + startPoint[1]
248
289
  + 'A ' + radius + ' ' + radius + ' 0 1 1 '
249
- + endPoint[0] + ' ' + endPoint[1]);
290
+ + endPoint[0] + ' ' + endPoint[1] + extraEnd);
291
+
250
292
 
251
293
  } else {
252
294
  const coords = Geometry.getCoords(item);
package/src/globals.ts CHANGED
@@ -33,7 +33,9 @@ export enum SymbolPinSide {
33
33
  export const portWidth = 20;
34
34
  export const portHeight = 2;
35
35
 
36
- export const defaultFont = 'Inter';
36
+ export const defaultFont = 'Open Sans-Regular, Arial';
37
+ export const defaultFontBold = 'Open Sans-Bold, Arial-Bold, Arial';
38
+
37
39
  export const defaultFontSize = 10;
38
40
 
39
41
  export const bodyColor = '#FFFEAF';
package/src/helpers.ts ADDED
@@ -0,0 +1,114 @@
1
+ import { writeFileSync } from "fs";
2
+ import { generateKiCADNetList } from "./export.js";
3
+ import { LayoutEngine } from "./layout.js";
4
+ import { SequenceAction } from "./objects/ExecutionScope.js";
5
+ import { parseFileWithVisitor } from "./parser.js";
6
+ import { generateSVG2 } from "./render.js";
7
+ import { SimpleStopwatch } from "./utils.js";
8
+ import { MainVisitor } from "./visitor.js";
9
+
10
+ export function renderScript(scriptData: string, outputPath: string, options): string {
11
+
12
+ const {
13
+ currentDirectory = null,
14
+ defaultLibsPath,
15
+ dumpNets = false,
16
+ dumpData = false,
17
+ kicadNetlistPath = null,
18
+ showStats = false} = options;
19
+
20
+ const visitor = new MainVisitor(true);
21
+
22
+ visitor.onImportFile = visitor.createImportFileHandler(currentDirectory, defaultLibsPath);
23
+
24
+ visitor.print('reading file');
25
+ visitor.print('done reading file');
26
+
27
+ const { tree, parser,
28
+ hasParseError, hasError,
29
+ parserTimeTaken,
30
+ lexerTimeTaken } = parseFileWithVisitor(visitor, scriptData);
31
+
32
+ showStats && console.log('Lexing took:', lexerTimeTaken);
33
+ showStats && console.log('Parsing took:', parserTimeTaken);
34
+ dumpNets && console.log(visitor.dumpNets());
35
+
36
+ dumpData && writeFileSync('dump/tree.lisp', tree.toStringTree(null, parser));
37
+ dumpData && writeFileSync('dump/raw-parser.txt', visitor.logger.dump());
38
+
39
+ if (hasError || hasParseError) {
40
+ console.log('Error while parsing');
41
+ return null;
42
+ }
43
+
44
+ try {
45
+ visitor.annotateComponents();
46
+ } catch (err) {
47
+ console.log('Error during annotation: ', err);
48
+ }
49
+
50
+ if (kicadNetlistPath) {
51
+ const kicadNetList = generateKiCADNetList(visitor.getNetList());
52
+ writeFileSync(kicadNetlistPath, kicadNetList);
53
+ console.log('Generated KiCad netlist file');
54
+ }
55
+
56
+
57
+ // await writeFile('dump/raw-netlist.json', JSON.stringify(visitor.dump2(), null, 2));
58
+
59
+ const { sequence, nets } = visitor.getGraph();
60
+
61
+ // const tmpInstances = visitor.getExecutor().scope.instances;
62
+ // for (const [instanceName, instance] of tmpInstances){
63
+ // console.log(instanceName);
64
+ // console.log(instance.pinNets);
65
+ // }
66
+
67
+
68
+ const tmpSequence = sequence.map(item => {
69
+ const tmp = [...item];
70
+
71
+ const action = tmp[0];
72
+
73
+ if (action === SequenceAction.Wire) {
74
+ tmp[2] = tmp[2].map(item2 => {
75
+ return [item2.direction, item2.value].join(",");
76
+ }).join(" ");
77
+ } else if (action === SequenceAction.Frame) {
78
+ tmp[1] = item[1].frameId;
79
+
80
+ } else if (action !== SequenceAction.WireJump) {
81
+ tmp[1] = item[1].instanceName;
82
+ }
83
+
84
+ return tmp.join(" | ");
85
+ });
86
+
87
+ dumpData && writeFileSync('dump/raw-sequence.txt', tmpSequence.join('\n'));
88
+ let svgOutput: string = null;
89
+
90
+ try {
91
+ const layoutEngine = new LayoutEngine();
92
+ const layoutTimer = new SimpleStopwatch();
93
+
94
+ const graph = layoutEngine.runLayout(sequence, nets);
95
+
96
+ layoutEngine.printWarnings();
97
+
98
+ showStats && console.log('Layout took:', layoutTimer.lap());
99
+
100
+ dumpData && writeFileSync('dump/raw-layout.txt', layoutEngine.logger.dump());
101
+
102
+ const generateSvgTimer = new SimpleStopwatch();
103
+ svgOutput = generateSVG2(graph);
104
+ showStats && console.log('Render took:', generateSvgTimer.lap());
105
+
106
+ if (outputPath) {
107
+ writeFileSync(outputPath, svgOutput);
108
+ }
109
+ } catch (err) {
110
+ console.log('Error during render: ', err);
111
+ }
112
+
113
+ return svgOutput;
114
+ }