circuitscript 0.0.14 → 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.
- package/.gitlab-ci.yml +22 -19
- package/__tests__/helpers.ts +12 -0
- package/__tests__/renderData/script1.cst.svg +1 -1
- package/__tests__/renderData/script2.cst.svg +1 -1
- package/__tests__/renderData/script3.cst.svg +1 -1
- package/__tests__/renderData/script4.cst +27 -5
- package/__tests__/renderData/script4.cst.svg +1 -1
- package/__tests__/renderData/script5.cst.svg +1 -1
- package/__tests__/testParse.ts +37 -2
- package/build/src/draw_symbols.js +207 -63
- package/build/src/geometry.js +35 -4
- package/build/src/helpers.js +7 -3
- package/build/src/layout.js +30 -17
- package/build/src/regenerate-tests.js +1 -1
- package/build/src/visitor.js +12 -4
- package/examples/example_arduino_uno.cst +390 -120
- package/examples/lib.cst +25 -28
- package/libs/lib.cst +23 -28
- package/package.json +1 -1
- package/src/draw_symbols.ts +270 -64
- package/src/geometry.ts +46 -5
- package/src/helpers.ts +8 -5
- package/src/layout.ts +42 -21
- package/src/regenerate-tests.ts +1 -1
- package/src/visitor.ts +16 -4
package/src/draw_symbols.ts
CHANGED
|
@@ -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';
|
|
@@ -198,7 +199,8 @@ export abstract class SymbolGraphic {
|
|
|
198
199
|
const position = tmpLabel.getLabelPosition();
|
|
199
200
|
const useFont = defaultFont;
|
|
200
201
|
|
|
201
|
-
const
|
|
202
|
+
const textContainer = group.group();
|
|
203
|
+
const text = textContainer.text(tmpLabel.text)
|
|
202
204
|
.fill('#333')
|
|
203
205
|
.font({
|
|
204
206
|
family: useFont,
|
|
@@ -208,12 +210,25 @@ export abstract class SymbolGraphic {
|
|
|
208
210
|
weight: fontWeight,
|
|
209
211
|
});
|
|
210
212
|
|
|
213
|
+
let translateX: number, translateY: number;
|
|
214
|
+
let useRotateAngle = 0;
|
|
215
|
+
|
|
211
216
|
if (isRotation180){
|
|
212
|
-
|
|
217
|
+
translateX = -position[0];
|
|
218
|
+
translateY = position[1];
|
|
219
|
+
useRotateAngle = 0;
|
|
213
220
|
} else {
|
|
214
|
-
|
|
215
|
-
|
|
221
|
+
translateX = position[0];
|
|
222
|
+
translateY = position[1];
|
|
223
|
+
useRotateAngle = this.angle;
|
|
216
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');
|
|
217
232
|
});
|
|
218
233
|
}
|
|
219
234
|
|
|
@@ -289,73 +304,233 @@ export class SymbolPlaceholder extends SymbolGraphic {
|
|
|
289
304
|
drawing.angle = this._angle;
|
|
290
305
|
const commands = drawing.getCommands();
|
|
291
306
|
|
|
292
|
-
drawing.log(drawing.id, 'angle: ', this._angle, "commands:", commands.length);
|
|
307
|
+
drawing.log('id: ', drawing.id, 'angle: ', this._angle, "commands:", commands.length);
|
|
293
308
|
|
|
294
309
|
commands.forEach(([commandName, positionParams, keywordParams]) => {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
drawing.log('add pin', ...positionParams);
|
|
301
|
-
drawing.addPin(...positionParams);
|
|
302
|
-
|
|
303
|
-
} else if (commandName === 'hline') {
|
|
304
|
-
drawing.log('add hline', ...positionParams);
|
|
305
|
-
drawing.addHLine(...positionParams);
|
|
306
|
-
|
|
307
|
-
} else if (commandName === 'vline') {
|
|
308
|
-
drawing.log('add vline', ...positionParams);
|
|
309
|
-
drawing.addVLine(...positionParams);
|
|
310
|
-
|
|
311
|
-
} else if (commandName === 'line') {
|
|
312
|
-
drawing.log('add line', ...positionParams);
|
|
313
|
-
drawing.addLine(...positionParams);
|
|
314
|
-
|
|
315
|
-
} else if (commandName === 'label') {
|
|
316
|
-
const keywords = ['fontSize', 'anchor', 'vanchor'];
|
|
317
|
-
|
|
318
|
-
// Create the style object
|
|
319
|
-
const style = {};
|
|
320
|
-
keywords.forEach(item => {
|
|
321
|
-
if (keywordParams.has(item)){
|
|
322
|
-
style[item] = keywordParams.get(item);
|
|
323
|
-
}
|
|
324
|
-
});
|
|
310
|
+
switch (commandName) {
|
|
311
|
+
case PlaceHolderCommands.rect:
|
|
312
|
+
drawing.log('add rect', ...positionParams);
|
|
313
|
+
drawing.addRect(...positionParams);
|
|
314
|
+
break;
|
|
325
315
|
|
|
326
|
-
|
|
327
|
-
|
|
316
|
+
case PlaceHolderCommands.hline:
|
|
317
|
+
drawing.log('add hline', ...positionParams);
|
|
318
|
+
drawing.addHLine(...positionParams);
|
|
319
|
+
break;
|
|
328
320
|
|
|
329
|
-
|
|
321
|
+
case PlaceHolderCommands.vline:
|
|
322
|
+
drawing.log('add vline', ...positionParams);
|
|
323
|
+
drawing.addVLine(...positionParams);
|
|
324
|
+
break;
|
|
330
325
|
|
|
331
|
-
|
|
332
|
-
|
|
326
|
+
case PlaceHolderCommands.line:
|
|
327
|
+
drawing.log('add line', ...positionParams);
|
|
328
|
+
drawing.addLine(...positionParams);
|
|
329
|
+
break;
|
|
333
330
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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
|
+
}
|
|
347
396
|
}
|
|
348
397
|
});
|
|
349
398
|
|
|
350
399
|
drawing.log("=== end generate drawing ===");
|
|
351
400
|
}
|
|
352
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
|
+
|
|
353
510
|
constructor(drawing: SymbolDrawing) {
|
|
354
511
|
super();
|
|
355
512
|
this.drawing = drawing;
|
|
356
513
|
}
|
|
357
514
|
}
|
|
358
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
|
+
|
|
359
534
|
export class SymbolCustom extends SymbolGraphic {
|
|
360
535
|
|
|
361
536
|
pinDefinition: SymbolPinDefintion[] = [];
|
|
@@ -403,7 +578,7 @@ export class SymbolCustom extends SymbolGraphic {
|
|
|
403
578
|
const bodyWidth = this.bodyWidth;
|
|
404
579
|
const bodyHeight = (1 + Math.max(maxLeftPins, maxRightPins)) * this.pinSpacing;
|
|
405
580
|
|
|
406
|
-
drawing.addSetFillColor(bodyColor);
|
|
581
|
+
// drawing.addSetFillColor(bodyColor);
|
|
407
582
|
|
|
408
583
|
drawing.addRect(0, 0, bodyWidth, bodyHeight);
|
|
409
584
|
|
|
@@ -451,18 +626,23 @@ export class SymbolCustom extends SymbolGraphic {
|
|
|
451
626
|
});
|
|
452
627
|
|
|
453
628
|
const instanceName = this.getLabelValue("refdes");
|
|
454
|
-
const MPN = this.getLabelValue("MPN");
|
|
455
|
-
|
|
456
629
|
instanceName && drawing.addLabel(-bodyWidth/2, -bodyHeight/2 - 4, instanceName, {
|
|
457
630
|
fontSize: 10,
|
|
458
631
|
anchor: HorizontalAlign.Left,
|
|
459
632
|
});
|
|
460
633
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
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
|
+
});
|
|
466
646
|
|
|
467
647
|
this.drawing = drawing;
|
|
468
648
|
this._cacheLeftPins = leftPins;
|
|
@@ -512,10 +692,13 @@ export class SymbolDrawing {
|
|
|
512
692
|
addPin(pinId: number, startX: number, startY: number,
|
|
513
693
|
endX: number, endY: number): SymbolDrawing {
|
|
514
694
|
|
|
515
|
-
// Determine the pin angle based on
|
|
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
|
|
516
700
|
|
|
517
701
|
let angle = 0;
|
|
518
|
-
|
|
519
702
|
if (startX === endX) {
|
|
520
703
|
if (startY > endY) {
|
|
521
704
|
angle = 270;
|
|
@@ -570,6 +753,29 @@ export class SymbolDrawing {
|
|
|
570
753
|
return this;
|
|
571
754
|
}
|
|
572
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
|
+
|
|
573
779
|
addRect2(x: number, y: number, x2: number, y2: number): SymbolDrawing {
|
|
574
780
|
this.items.push(
|
|
575
781
|
Geometry.polygon([
|
|
@@ -820,7 +1026,7 @@ export class SymbolDrawingCommands extends SymbolDrawing {
|
|
|
820
1026
|
clone(): SymbolDrawingCommands {
|
|
821
1027
|
// Force a deep clone
|
|
822
1028
|
const tmpCommands: SubExpressionCommand[] = this.commands.map(item => {
|
|
823
|
-
if (item[0] ===
|
|
1029
|
+
if (item[0] === PlaceHolderCommands.label) {
|
|
824
1030
|
const commandName = item[0];
|
|
825
1031
|
const positionParams = item[1];
|
|
826
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,6 +65,18 @@ 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,
|
|
@@ -71,7 +86,7 @@ export class Label extends Flatten.Polygon {
|
|
|
71
86
|
// Determine the size of the text, this is needed to determine the
|
|
72
87
|
// bounding box of the text for layout purposes.
|
|
73
88
|
const { width, height, box } =
|
|
74
|
-
measureTextSize2(
|
|
89
|
+
measureTextSize2(useText, defaultFont, fontSize, fontWeight,
|
|
75
90
|
anchor, vanchor);
|
|
76
91
|
|
|
77
92
|
// const polygonCoords =
|
|
@@ -88,7 +103,7 @@ export class Label extends Flatten.Polygon {
|
|
|
88
103
|
const polygon = new Flatten.Polygon(polygonCoords);
|
|
89
104
|
|
|
90
105
|
// Create the bounds of the label
|
|
91
|
-
return new Label(id,
|
|
106
|
+
return new Label(id, useText, [x, y], polygon, style, box);
|
|
92
107
|
}
|
|
93
108
|
|
|
94
109
|
rotate(angle: number, origin: Flatten.Point): Label {
|
|
@@ -117,6 +132,13 @@ export class Geometry {
|
|
|
117
132
|
return new Flatten.Point(x, y);
|
|
118
133
|
}
|
|
119
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
|
+
|
|
120
142
|
static label(id: string, x: number, y: number, text: string, style: LabelStyle): Label {
|
|
121
143
|
return Label.fromPoint(id, x, y, text, style);
|
|
122
144
|
}
|
|
@@ -188,7 +210,14 @@ export class Geometry {
|
|
|
188
210
|
|
|
189
211
|
features.forEach(feature => {
|
|
190
212
|
const box = feature.box;
|
|
191
|
-
|
|
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) {
|
|
192
221
|
throw "Invalid box!";
|
|
193
222
|
}
|
|
194
223
|
|
|
@@ -219,6 +248,8 @@ export class Geometry {
|
|
|
219
248
|
console.log('unknown type', feature);
|
|
220
249
|
}
|
|
221
250
|
|
|
251
|
+
static FullCircleRadians = 2 * Math.PI;
|
|
252
|
+
|
|
222
253
|
static featuresToPath(items: Feature[]):
|
|
223
254
|
{ path: string, isClosedPolygon: boolean } {
|
|
224
255
|
|
|
@@ -238,16 +269,26 @@ export class Geometry {
|
|
|
238
269
|
const y = item.center.y;
|
|
239
270
|
const radius = item.r as number;
|
|
240
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
|
+
|
|
241
281
|
// Assume angle is clockwise for now
|
|
242
282
|
const startPoint = getArcPointRadians(x, y, radius,
|
|
243
283
|
item.startAngle);
|
|
244
284
|
|
|
245
285
|
const endPoint = getArcPointRadians(x, y, radius,
|
|
246
|
-
|
|
286
|
+
useEndAngle);
|
|
247
287
|
|
|
248
288
|
paths.push('M ' + startPoint[0] + ' ' + startPoint[1]
|
|
249
289
|
+ 'A ' + radius + ' ' + radius + ' 0 1 1 '
|
|
250
|
-
+ endPoint[0] + ' ' + endPoint[1]);
|
|
290
|
+
+ endPoint[0] + ' ' + endPoint[1] + extraEnd);
|
|
291
|
+
|
|
251
292
|
|
|
252
293
|
} else {
|
|
253
294
|
const coords = Geometry.getCoords(item);
|
package/src/helpers.ts
CHANGED
|
@@ -41,7 +41,11 @@ export function renderScript(scriptData: string, outputPath: string, options): s
|
|
|
41
41
|
return null;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
try {
|
|
45
|
+
visitor.annotateComponents();
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.log('Error during annotation: ', err);
|
|
48
|
+
}
|
|
45
49
|
|
|
46
50
|
if (kicadNetlistPath) {
|
|
47
51
|
const kicadNetList = generateKiCADNetList(visitor.getNetList());
|
|
@@ -99,12 +103,11 @@ export function renderScript(scriptData: string, outputPath: string, options): s
|
|
|
99
103
|
svgOutput = generateSVG2(graph);
|
|
100
104
|
showStats && console.log('Render took:', generateSvgTimer.lap());
|
|
101
105
|
|
|
102
|
-
if (outputPath){
|
|
106
|
+
if (outputPath) {
|
|
103
107
|
writeFileSync(outputPath, svgOutput);
|
|
104
|
-
}
|
|
108
|
+
}
|
|
105
109
|
} catch (err) {
|
|
106
|
-
console.log('
|
|
107
|
-
console.log(err)
|
|
110
|
+
console.log('Error during render: ', err);
|
|
108
111
|
}
|
|
109
112
|
|
|
110
113
|
return svgOutput;
|
package/src/layout.ts
CHANGED
|
@@ -604,10 +604,6 @@ export class LayoutEngine {
|
|
|
604
604
|
if (tmpSymbol instanceof SymbolCustom && widthProp){
|
|
605
605
|
tmpSymbol.bodyWidth = widthProp;
|
|
606
606
|
}
|
|
607
|
-
|
|
608
|
-
if (component.assignedRefDes !== null){
|
|
609
|
-
tmpSymbol.setLabelValue("refdes", component.assignedRefDes);
|
|
610
|
-
}
|
|
611
607
|
|
|
612
608
|
if (!didSetAngle && component.parameters.has('_addDirection')){
|
|
613
609
|
// If there is an _addDirection specified, then the angle
|
|
@@ -683,8 +679,31 @@ export class LayoutEngine {
|
|
|
683
679
|
|
|
684
680
|
previousNode = wireName;
|
|
685
681
|
previousPin = 1;
|
|
686
|
-
|
|
687
|
-
|
|
682
|
+
|
|
683
|
+
const wireSegmentsInfo = wireSegments.map(item => {
|
|
684
|
+
const tmp: {
|
|
685
|
+
direction: string,
|
|
686
|
+
value: number,
|
|
687
|
+
valueXY?: [x: number, y: number],
|
|
688
|
+
until?: [instanceName: string, pin: number]
|
|
689
|
+
} = {
|
|
690
|
+
direction: item.direction,
|
|
691
|
+
value: item.value,
|
|
692
|
+
};
|
|
693
|
+
|
|
694
|
+
if (item.valueXY) {
|
|
695
|
+
tmp.valueXY = item.valueXY;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
if (item.until) {
|
|
699
|
+
tmp.until = [item.until[0].toString(), item.until[1]];
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
return tmp;
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
this.print(SequenceAction.Wire, wireId,
|
|
706
|
+
JSON.stringify(wireSegmentsInfo));
|
|
688
707
|
|
|
689
708
|
} else if (action === SequenceAction.WireJump) {
|
|
690
709
|
this.print(...sequence[i]);
|
|
@@ -1338,26 +1357,28 @@ function applyComponentParamsToSymbol(typeProp: string,
|
|
|
1338
1357
|
component: ClassComponent, symbol: SymbolGraphic): void {
|
|
1339
1358
|
|
|
1340
1359
|
if (typeProp === 'net') {
|
|
1341
|
-
symbol.setLabelValue("net_name",
|
|
1360
|
+
symbol.setLabelValue("net_name",
|
|
1361
|
+
component.parameters.get(ParamKeys.net_name) as string);
|
|
1342
1362
|
}
|
|
1343
1363
|
|
|
1344
|
-
if (component.
|
|
1345
|
-
|
|
1346
|
-
let displayString = "";
|
|
1347
|
-
const tmpValue = component.parameters.get('value');
|
|
1348
|
-
if (typeof tmpValue == 'object' && (tmpValue instanceof NumericValue)) {
|
|
1349
|
-
displayString = (tmpValue as NumericValue).toDisplayString();
|
|
1350
|
-
} else {
|
|
1351
|
-
displayString = tmpValue;
|
|
1352
|
-
}
|
|
1353
|
-
|
|
1354
|
-
symbol.setLabelValue('value', displayString);
|
|
1364
|
+
if (component.assignedRefDes !== null){
|
|
1365
|
+
symbol.setLabelValue("refdes", component.assignedRefDes);
|
|
1355
1366
|
}
|
|
1356
1367
|
|
|
1357
|
-
|
|
1368
|
+
for (const [key, value] of component.parameters) {
|
|
1369
|
+
if (key !== 'refdes' && key !== 'net_name') {
|
|
1370
|
+
let useValue: string;
|
|
1371
|
+
|
|
1372
|
+
if (typeof value == 'object' && (value instanceof NumericValue)) {
|
|
1373
|
+
useValue = (value as NumericValue).toDisplayString();
|
|
1374
|
+
} else if (typeof value === 'number') {
|
|
1375
|
+
useValue = value.toString();
|
|
1376
|
+
} else if (typeof value === 'string'){
|
|
1377
|
+
useValue = value;
|
|
1378
|
+
}
|
|
1358
1379
|
|
|
1359
|
-
|
|
1360
|
-
|
|
1380
|
+
symbol.setLabelValue(key, useValue);
|
|
1381
|
+
}
|
|
1361
1382
|
}
|
|
1362
1383
|
}
|
|
1363
1384
|
|
package/src/regenerate-tests.ts
CHANGED