circuitscript 0.0.22 → 0.0.25

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.
Files changed (180) hide show
  1. package/dist/cjs/BaseVisitor.js +487 -0
  2. package/dist/cjs/SemanticTokenVisitor.js +218 -0
  3. package/dist/cjs/SymbolValidatorVisitor.js +233 -0
  4. package/dist/cjs/antlr/CircuitScriptLexer.js +302 -0
  5. package/dist/cjs/antlr/CircuitScriptParser.js +5128 -0
  6. package/dist/cjs/antlr/CircuitScriptVisitor.js +7 -0
  7. package/dist/cjs/draw_symbols.js +819 -0
  8. package/dist/cjs/execute.js +778 -0
  9. package/{src/export.ts → dist/cjs/export.js} +34 -56
  10. package/dist/cjs/fonts.js +4 -0
  11. package/dist/cjs/geometry.js +450 -0
  12. package/dist/cjs/globals.js +60 -0
  13. package/dist/cjs/helpers.js +269 -0
  14. package/dist/cjs/index.js +31 -0
  15. package/{src/layout.ts → dist/cjs/layout.js} +421 -1002
  16. package/dist/cjs/lexer.js +111 -0
  17. package/dist/cjs/logger.js +17 -0
  18. package/dist/cjs/main.js +82 -0
  19. package/dist/cjs/objects/ClassComponent.js +145 -0
  20. package/dist/cjs/objects/ExecutionScope.js +135 -0
  21. package/dist/cjs/objects/Frame.js +22 -0
  22. package/{src/objects/Net.ts → dist/cjs/objects/Net.js} +9 -24
  23. package/dist/cjs/objects/ParamDefinition.js +42 -0
  24. package/dist/cjs/objects/PinDefinition.js +31 -0
  25. package/dist/cjs/objects/PinTypes.js +11 -0
  26. package/dist/cjs/objects/Wire.js +9 -0
  27. package/dist/cjs/objects/types.js +15 -0
  28. package/dist/cjs/parser.js +70 -0
  29. package/dist/cjs/regenerate-tests.js +23 -0
  30. package/dist/cjs/render.js +155 -0
  31. package/{src/server.ts → dist/cjs/server.js} +15 -21
  32. package/dist/cjs/sizing.js +105 -0
  33. package/{src/utils.ts → dist/cjs/utils.js} +25 -35
  34. package/dist/cjs/validate.js +81 -0
  35. package/dist/cjs/visitor.js +844 -0
  36. package/dist/esm/BaseVisitor.mjs +488 -0
  37. package/dist/esm/SemanticTokenVisitor.mjs +215 -0
  38. package/dist/esm/SymbolValidatorVisitor.mjs +222 -0
  39. package/dist/esm/antlr/CircuitScriptLexer.mjs +276 -0
  40. package/dist/esm/antlr/CircuitScriptParser.mjs +5038 -0
  41. package/{build/src/antlr/CircuitScriptVisitor.js → dist/esm/antlr/CircuitScriptVisitor.mjs} +8 -3
  42. package/{build/src/draw_symbols.js → dist/esm/draw_symbols.mjs} +78 -33
  43. package/{build/src/execute.js → dist/esm/execute.mjs} +59 -60
  44. package/{build/src/export.js → dist/esm/export.mjs} +2 -2
  45. package/{build/src/geometry.js → dist/esm/geometry.mjs} +31 -15
  46. package/dist/esm/helpers.mjs +252 -0
  47. package/dist/esm/index.mjs +15 -0
  48. package/{build/src/layout.js → dist/esm/layout.mjs} +19 -11
  49. package/{build/src/lexer.js → dist/esm/lexer.mjs} +10 -10
  50. package/{build/src/main.js → dist/esm/main.mjs} +9 -14
  51. package/{build/src/objects/ClassComponent.js → dist/esm/objects/ClassComponent.mjs} +6 -3
  52. package/{build/src/objects/ExecutionScope.js → dist/esm/objects/ExecutionScope.mjs} +1 -0
  53. package/{build/src/objects/PinDefinition.js → dist/esm/objects/PinDefinition.mjs} +1 -1
  54. package/dist/esm/objects/types.mjs +12 -0
  55. package/dist/esm/parser.mjs +64 -0
  56. package/{build/src/regenerate-tests.js → dist/esm/regenerate-tests.mjs} +1 -1
  57. package/{build/src/render.js → dist/esm/render.mjs} +7 -24
  58. package/{build/src/sizing.js → dist/esm/sizing.mjs} +22 -8
  59. package/{src/main.ts → dist/esm/validate.mjs} +31 -62
  60. package/dist/esm/visitor.mjs +838 -0
  61. package/dist/types/BaseVisitor.d.ts +69 -0
  62. package/dist/types/SemanticTokenVisitor.d.ts +36 -0
  63. package/dist/types/SymbolValidatorVisitor.d.ts +61 -0
  64. package/{build/src → dist/types}/antlr/CircuitScriptLexer.d.ts +28 -27
  65. package/dist/types/antlr/CircuitScriptParser.d.ts +719 -0
  66. package/{build/src → dist/types}/antlr/CircuitScriptVisitor.d.ts +69 -59
  67. package/{build/src → dist/types}/draw_symbols.d.ts +11 -2
  68. package/{build/src → dist/types}/execute.d.ts +6 -9
  69. package/{build/src → dist/types}/geometry.d.ts +5 -1
  70. package/dist/types/helpers.d.ts +40 -0
  71. package/dist/types/index.d.ts +15 -0
  72. package/{build/src → dist/types}/layout.d.ts +10 -10
  73. package/{build/src → dist/types}/lexer.d.ts +2 -2
  74. package/{build/src → dist/types}/objects/ClassComponent.d.ts +2 -2
  75. package/{build/src → dist/types}/objects/ExecutionScope.d.ts +4 -1
  76. package/{build/src → dist/types}/objects/PinDefinition.d.ts +1 -1
  77. package/{build/src → dist/types}/objects/types.d.ts +5 -0
  78. package/dist/types/parser.d.ts +25 -0
  79. package/{build/src → dist/types}/render.d.ts +1 -1
  80. package/{build/src → dist/types}/sizing.d.ts +3 -1
  81. package/dist/types/validate.d.ts +2 -0
  82. package/dist/types/visitor.d.ts +80 -0
  83. package/libs/lib.cst +0 -2
  84. package/package.json +38 -15
  85. package/.editorconfig +0 -15
  86. package/.eslintignore +0 -1
  87. package/.eslintrc.json +0 -27
  88. package/.gitlab-ci.yml +0 -81
  89. package/.prettierignore +0 -8
  90. package/.prettierrc +0 -16
  91. package/__tests__/expectedResults.ts +0 -657
  92. package/__tests__/helpers.ts +0 -82
  93. package/__tests__/parseScripts.ts +0 -593
  94. package/__tests__/renderData/script1.cst +0 -58
  95. package/__tests__/renderData/script1.cst.svg +0 -1
  96. package/__tests__/renderData/script2.cst +0 -16
  97. package/__tests__/renderData/script2.cst.svg +0 -1
  98. package/__tests__/renderData/script3.cst +0 -30
  99. package/__tests__/renderData/script3.cst.svg +0 -1
  100. package/__tests__/renderData/script4.cst +0 -54
  101. package/__tests__/renderData/script4.cst.svg +0 -1
  102. package/__tests__/renderData/script5.cst +0 -23
  103. package/__tests__/renderData/script5.cst.svg +0 -1
  104. package/__tests__/renderData/script6.cst +0 -28
  105. package/__tests__/renderData/script6.cst.svg +0 -1
  106. package/__tests__/renderData/script7.cst +0 -26
  107. package/__tests__/renderData/script7.cst.svg +0 -1
  108. package/__tests__/renderData/script8.cst +0 -37
  109. package/__tests__/renderData/script8.cst.svg +0 -1
  110. package/__tests__/testCLI.ts +0 -68
  111. package/__tests__/testMathOps.ts +0 -36
  112. package/__tests__/testMergeWires.ts +0 -141
  113. package/__tests__/testParse.ts +0 -263
  114. package/__tests__/testRender.ts +0 -38
  115. package/build/src/antlr/CircuitScriptLexer.js +0 -287
  116. package/build/src/antlr/CircuitScriptParser.d.ts +0 -674
  117. package/build/src/antlr/CircuitScriptParser.js +0 -4841
  118. package/build/src/helpers.d.ts +0 -1
  119. package/build/src/helpers.js +0 -73
  120. package/build/src/objects/types.js +0 -6
  121. package/build/src/parser.js +0 -69
  122. package/build/src/visitor.d.ts +0 -133
  123. package/build/src/visitor.js +0 -1154
  124. package/documentation.md +0 -238
  125. package/examples/example_arduino_uno.cst +0 -1146
  126. package/examples/example_garden_pump.cst +0 -567
  127. package/examples/lib.cst +0 -185
  128. package/jest.config.js +0 -23
  129. package/refresh.html +0 -42
  130. package/server.cjs +0 -50
  131. package/src/antlr/CircuitScript.g4 +0 -209
  132. package/src/antlr/CircuitScriptLexer.ts +0 -317
  133. package/src/antlr/CircuitScriptParser.ts +0 -4979
  134. package/src/antlr/CircuitScriptVisitor.ts +0 -420
  135. package/src/draw_symbols.ts +0 -1085
  136. package/src/execute.ts +0 -1227
  137. package/src/fonts.ts +0 -1
  138. package/src/geometry.ts +0 -638
  139. package/src/globals.ts +0 -67
  140. package/src/helpers.ts +0 -114
  141. package/src/lexer.ts +0 -151
  142. package/src/logger.ts +0 -17
  143. package/src/objects/ClassComponent.ts +0 -223
  144. package/src/objects/ExecutionScope.ts +0 -201
  145. package/src/objects/Frame.ts +0 -20
  146. package/src/objects/ParamDefinition.ts +0 -49
  147. package/src/objects/PinDefinition.ts +0 -49
  148. package/src/objects/PinTypes.ts +0 -7
  149. package/src/objects/Wire.ts +0 -19
  150. package/src/objects/types.ts +0 -66
  151. package/src/parser.ts +0 -106
  152. package/src/regenerate-tests.ts +0 -25
  153. package/src/render.ts +0 -260
  154. package/src/sizing.ts +0 -96
  155. package/src/visitor.ts +0 -1691
  156. package/tsconfig.json +0 -27
  157. package/tsconfig.release.json +0 -8
  158. /package/{build/src/fonts.js → dist/esm/fonts.mjs} +0 -0
  159. /package/{build/src/globals.js → dist/esm/globals.mjs} +0 -0
  160. /package/{build/src/logger.js → dist/esm/logger.mjs} +0 -0
  161. /package/{build/src/objects/Frame.js → dist/esm/objects/Frame.mjs} +0 -0
  162. /package/{build/src/objects/Net.js → dist/esm/objects/Net.mjs} +0 -0
  163. /package/{build/src/objects/ParamDefinition.js → dist/esm/objects/ParamDefinition.mjs} +0 -0
  164. /package/{build/src/objects/PinTypes.js → dist/esm/objects/PinTypes.mjs} +0 -0
  165. /package/{build/src/objects/Wire.js → dist/esm/objects/Wire.mjs} +0 -0
  166. /package/{build/src/server.js → dist/esm/server.mjs} +0 -0
  167. /package/{build/src/utils.js → dist/esm/utils.mjs} +0 -0
  168. /package/{build/src → dist/types}/export.d.ts +0 -0
  169. /package/{build/src → dist/types}/fonts.d.ts +0 -0
  170. /package/{build/src → dist/types}/globals.d.ts +0 -0
  171. /package/{build/src → dist/types}/logger.d.ts +0 -0
  172. /package/{build/src → dist/types}/main.d.ts +0 -0
  173. /package/{build/src → dist/types}/objects/Frame.d.ts +0 -0
  174. /package/{build/src → dist/types}/objects/Net.d.ts +0 -0
  175. /package/{build/src → dist/types}/objects/ParamDefinition.d.ts +0 -0
  176. /package/{build/src → dist/types}/objects/PinTypes.d.ts +0 -0
  177. /package/{build/src → dist/types}/objects/Wire.d.ts +0 -0
  178. /package/{build/src → dist/types}/regenerate-tests.d.ts +0 -0
  179. /package/{build/src → dist/types}/server.d.ts +0 -0
  180. /package/{build/src → dist/types}/utils.d.ts +0 -0
@@ -1,1085 +0,0 @@
1
- import { G } from "@svgdotjs/svg.js";
2
-
3
- import { SymbolPinSide, bodyColor, defaultFontBold, defaultFont } from "./globals.js";
4
- import { Feature, Geometry, GeometryProp, HorizontalAlign, Label, LabelStyle, VerticalAlign } from "./geometry.js";
5
- import { Logger } from "./logger.js";
6
-
7
-
8
- /**
9
- * Symbols should also define where their ports
10
- */
11
-
12
- const defaultSymbolLineColor = '#333';
13
- const defaultSymbolLineWidth = 2;
14
-
15
- export abstract class SymbolGraphic {
16
-
17
- drawPortsName = true;
18
-
19
- displayBounds = true;
20
-
21
- drawing: SymbolDrawing;
22
-
23
- _angle = 0;
24
-
25
- width: number;
26
- height: number;
27
-
28
- // Stores a reference of <labelID> to the label value
29
- labelTexts = new Map<string, string>();
30
-
31
- get angle(): number {
32
- return (this._angle % 360);
33
- }
34
-
35
- set angle(value: number) {
36
- this._angle = value;
37
- }
38
-
39
- refreshDrawing(calculateSize = true): void {
40
- this.generateDrawing();
41
- calculateSize && this.calculateSize();
42
- }
43
-
44
- calculateSize(): void {
45
- const { width, height } = this.drawing.getBoundingBox();
46
- this.width = width;
47
- this.height = height;
48
- }
49
-
50
- // Subclasses should implement this
51
- abstract generateDrawing(): void;
52
-
53
- size(): { width: number; height: number; } {
54
- return {
55
- width: this.width,
56
- height: this.height
57
- }
58
- }
59
-
60
- draw(group: G, extra?: {}): void {
61
- // Assume that the symbol is vertical
62
- const innerGroup = group.group();
63
-
64
- this.drawBody(innerGroup);
65
-
66
- this.drawPins(innerGroup);
67
-
68
- this.drawLabels(innerGroup);
69
-
70
- this.drawPlaceRemove(innerGroup, extra);
71
-
72
- // this.displayBounds && this.drawBounds(group);
73
- }
74
-
75
- drawPlaceRemove(group: G, extra?: { place?: boolean }): void {
76
- if (extra && extra.place === false) {
77
- // Do not place this component!
78
- // Draw the x
79
- const { start, end } = this.drawing.getBoundingBox(true);
80
-
81
- group.path([
82
- "M", start[0], start[1], "L", end[0], end[1],
83
- "M", end[0], start[1], "L", start[0], end[1]
84
- ].join(" "))
85
- .stroke({
86
- width: defaultSymbolLineWidth,
87
- color: 'red'
88
- });
89
- }
90
- }
91
-
92
- // Returns the port position, relative to the symbol origin
93
- pinPosition(id: number): { x: number; y: number; angle: number; } {
94
- const pin = this.drawing.getPinPosition(id);
95
-
96
- // Allow pin position values to be rounded to 4 d.p
97
- const [x, y] = pin.start;
98
- const useX = Math.round(x * 10000) / 10000;
99
- const useY = Math.round(y * 10000 / 10000);
100
-
101
- if (pin) {
102
- return {
103
- x: useX,
104
- y: useY,
105
- angle: pin.angle,
106
- }
107
- }
108
- }
109
-
110
- protected drawBounds(group: G): void {
111
- const bbox = this.drawing.getBoundingBox();
112
-
113
- group.circle(3)
114
- .translate(-3 / 2, -3 / 2)
115
- .fill('red')
116
- .stroke('none');
117
-
118
- group.rect(bbox.width, bbox.height)
119
- .translate(bbox.start[0], bbox.start[1])
120
- .fill('none')
121
- .stroke({
122
- width: 1,
123
- color: '#ccc',
124
- })
125
- }
126
-
127
- protected drawBody(group: G): void {
128
- // Draws the symbol body
129
-
130
- const paths = this.drawing.getPaths();
131
- paths.forEach(pathInfo => {
132
- const {path, lineColor, fillColor, lineWidth} = pathInfo;
133
- group.path(path)
134
- .stroke({
135
- width: lineWidth,
136
- color: lineColor,
137
- })
138
- .fill(fillColor)
139
- });
140
- }
141
-
142
- protected drawPins(group: G): void {
143
- // Draw pins
144
- group.path(this.drawing.getPinsPath())
145
- .stroke({
146
- width: defaultSymbolLineWidth,
147
- color: '#333',
148
- });
149
- }
150
-
151
- protected drawLabels(group: G): void {
152
- const labels = this.drawing.getLabels();
153
-
154
- labels.forEach(label => {
155
- const tmpLabel = label as Label;
156
-
157
- const {
158
- fontSize = 10,
159
- anchor = HorizontalAlign.Left,
160
- vanchor = VerticalAlign.Bottom,
161
- fontWeight = 'regular',
162
- angle: labelAngle = 0,
163
- } = tmpLabel.style ?? {};
164
-
165
- let anchorStyle = 'start';
166
- let dominantBaseline = 'auto';
167
-
168
- let useAnchor = anchor;
169
- let useDominantBaseline = vanchor;
170
- const isRotation180 = Math.abs(this.angle) === 180;
171
-
172
- if (isRotation180) {
173
- // Special case to flip the text instead of rotating
174
- useAnchor = this.flipTextAnchor(anchor);
175
- useDominantBaseline = this.flipDominantBaseline(vanchor);
176
- }
177
-
178
- switch(useAnchor){
179
- case HorizontalAlign.Left:
180
- anchorStyle = 'start';
181
- break;
182
-
183
- case HorizontalAlign.Middle:
184
- anchorStyle = 'middle';
185
- break;
186
-
187
- case HorizontalAlign.Right:
188
- anchorStyle = 'end';
189
- break;
190
- }
191
-
192
- switch(useDominantBaseline){
193
- case VerticalAlign.Top:
194
- dominantBaseline = 'hanging';
195
- break;
196
-
197
- case VerticalAlign.Middle:
198
- dominantBaseline = 'middle';
199
- break;
200
-
201
- case VerticalAlign.Bottom:
202
- dominantBaseline = 'text-top';
203
- break;
204
- }
205
-
206
- const position = tmpLabel.getLabelPosition();
207
- const useFont = defaultFont;
208
-
209
- const textContainer = group.group();
210
- const text = textContainer.text(tmpLabel.text)
211
- .fill('#333')
212
- .font({
213
- family: useFont,
214
- size: fontSize,
215
- anchor: anchorStyle,
216
- 'dominant-baseline': dominantBaseline,
217
- weight: fontWeight,
218
- });
219
-
220
- let translateX: number, translateY: number;
221
- let useRotateAngle = 0;
222
-
223
- if (isRotation180){
224
- translateX = -position[0];
225
- translateY = -position[1];
226
- useRotateAngle = 0;
227
- } else {
228
- translateX = position[0];
229
- translateY = position[1];
230
- useRotateAngle = this.angle;
231
- }
232
-
233
- text.rotate(labelAngle);
234
- textContainer.translate(translateX, translateY)
235
- .rotate(useRotateAngle, -translateX, -translateY);
236
-
237
- // For debug, show the origin of the text container
238
- // textContainer.circle(2).fill('red');
239
- });
240
- }
241
-
242
- flipTextAnchor(value: HorizontalAlign): HorizontalAlign {
243
- if (value === HorizontalAlign.Left) {
244
- return HorizontalAlign.Right
245
- } else if (value === HorizontalAlign.Right) {
246
- return HorizontalAlign.Left;
247
- } else {
248
- return HorizontalAlign.Middle;
249
- }
250
- }
251
-
252
- flipDominantBaseline(value: VerticalAlign): VerticalAlign {
253
- if (value === VerticalAlign.Top) {
254
- return VerticalAlign.Bottom;
255
- } else if (value === VerticalAlign.Bottom) {
256
- return VerticalAlign.Top;
257
- } else {
258
- return VerticalAlign.Middle;
259
- }
260
- }
261
-
262
- setLabelValue(labelId: string, labelValue: string): void {
263
- this.labelTexts.set(labelId, labelValue);
264
- }
265
-
266
- getLabelValue(labelId: string): string {
267
- if (this.labelTexts.has(labelId)) {
268
- return this.labelTexts.get(labelId);
269
- }
270
- }
271
- }
272
-
273
- export function SymbolFactory(name: string): SymbolGraphic | null {
274
- switch (name) {
275
- case 'point':
276
- return new SymbolPointHidden();
277
- }
278
- }
279
-
280
- export class SymbolPointHidden extends SymbolGraphic {
281
- generateDrawing(): void {
282
- const drawing = new SymbolDrawing();
283
- drawing.addPin(1, 0, 0, 0, 0);
284
-
285
- this.drawing = drawing;
286
- }
287
- }
288
-
289
- export class SymbolText extends SymbolGraphic {
290
-
291
- text: string;
292
- fontSize = 10;
293
- fontWeight = 'regular';
294
-
295
- constructor(text: string){
296
- super();
297
- this.text = text;
298
- }
299
-
300
- generateDrawing(): void {
301
- const drawing = new SymbolDrawing();
302
- drawing.addLabel(0, 0, this.text, {
303
- fontSize: this.fontSize,
304
- anchor: HorizontalAlign.Middle,
305
- fontWeight: this.fontWeight,
306
- });
307
-
308
- this.drawing = drawing;
309
- }
310
- }
311
-
312
- export class SymbolPlaceholder extends SymbolGraphic {
313
- // This is used if the drawing object is defined within
314
- // circuitscript code itself.
315
- generateDrawing(): void {
316
- const drawing = this.drawing as SymbolDrawingCommands;
317
-
318
- drawing.log("=== start generate drawing ===");
319
-
320
- drawing.clear();
321
- drawing.angle = this._angle;
322
- const commands = drawing.getCommands();
323
-
324
- drawing.log('id: ', drawing.id, 'angle: ', this._angle, "commands:", commands.length);
325
-
326
- commands.forEach(([commandName, positionParams, keywordParams]) => {
327
- switch (commandName) {
328
- case PlaceHolderCommands.rect:
329
- drawing.log('add rect', ...positionParams);
330
- drawing.addRect(...positionParams);
331
- break;
332
-
333
- case PlaceHolderCommands.hline:
334
- drawing.log('add hline', ...positionParams);
335
- drawing.addHLine(...positionParams);
336
- break;
337
-
338
- case PlaceHolderCommands.vline:
339
- drawing.log('add vline', ...positionParams);
340
- drawing.addVLine(...positionParams);
341
- break;
342
-
343
- case PlaceHolderCommands.line:
344
- drawing.log('add line', ...positionParams);
345
- drawing.addLine(...positionParams);
346
- break;
347
-
348
- case PlaceHolderCommands.path:
349
- drawing.addPath(...positionParams);
350
- break;
351
-
352
- case PlaceHolderCommands.lineWidth:
353
- drawing.addSetLineWidth(...positionParams);
354
- break;
355
-
356
- case PlaceHolderCommands.fill:
357
- drawing.addSetFillColor(...positionParams);
358
- break;
359
-
360
- case PlaceHolderCommands.lineColor:
361
- drawing.addSetLineColor(...positionParams);
362
- break;
363
-
364
- case PlaceHolderCommands.arc:
365
- drawing.addArc(...positionParams);
366
- break;
367
-
368
- case PlaceHolderCommands.circle:
369
- // circle params: center x, center y, radius
370
- drawing.addArc(...positionParams, 0, 360);
371
- break;
372
-
373
- case PlaceHolderCommands.triangle:
374
- drawing.addTriangle(...positionParams);
375
- break;
376
-
377
- case PlaceHolderCommands.pin:
378
- case PlaceHolderCommands.hpin:
379
- case PlaceHolderCommands.vpin:
380
- {
381
- this.drawPinParams(drawing, commandName,
382
- keywordParams, positionParams);
383
- break;
384
- }
385
-
386
- case PlaceHolderCommands.label: {
387
- const keywords = ['fontSize', 'anchor', 'vanchor', 'angle'];
388
-
389
- // Create the style object
390
- const style = {};
391
- keywords.forEach(item => {
392
- if (keywordParams.has(item)) {
393
- style[item] = keywordParams.get(item);
394
- }
395
- });
396
-
397
- positionParams = [...positionParams];
398
- positionParams.push(style);
399
-
400
- const labelId = positionParams[0];
401
-
402
- const tmpPositionParams = [...positionParams];
403
-
404
- const tmpLabelValue = this.getLabelValue(labelId);
405
- if (tmpLabelValue !== undefined) {
406
- tmpPositionParams[3] = tmpLabelValue;
407
- }
408
-
409
- drawing.log('add label', JSON.stringify(tmpPositionParams));
410
- drawing.addLabelId(...tmpPositionParams);
411
- break;
412
- }
413
- }
414
- });
415
-
416
- drawing.log("=== end generate drawing ===");
417
- }
418
-
419
- drawPinParams(drawing: SymbolDrawingCommands,
420
- commandName: string, keywordParams: Map<string, any>,
421
- positionParams: any[]): void {
422
-
423
- drawing.log('add pin', ...positionParams);
424
-
425
- const keywordDisplayPinId = 'display_pin_id';
426
- let displayPinId = true;
427
-
428
- if (keywordParams.has(keywordDisplayPinId)) {
429
- if (keywordParams.get(keywordDisplayPinId) === 0) {
430
- displayPinId = false;
431
- }
432
- }
433
-
434
- let pinNameParam: string | null = null;
435
- if (typeof positionParams[1] === 'string') {
436
- // If the type of the second position is a string, then
437
- // use the string value as the pin name
438
- pinNameParam = positionParams[1];
439
- positionParams = [positionParams[0], ...positionParams.slice(2)];
440
- }
441
-
442
- // create the next point
443
- const startX = positionParams[1];
444
- const startY = positionParams[2];
445
-
446
- if (commandName === PlaceHolderCommands.vpin) {
447
- const magnitude = positionParams[3];
448
- positionParams = [
449
- positionParams[0],
450
- startX,
451
- startY,
452
- startX,
453
- startY + magnitude
454
- ];
455
- } else if (commandName === PlaceHolderCommands.hpin) {
456
- const magnitude = positionParams[3];
457
- positionParams = [
458
- positionParams[0],
459
- startX,
460
- startY,
461
- startX + magnitude,
462
- startY
463
- ];
464
- }
465
-
466
- drawing.addPin(...positionParams);
467
-
468
- // Add a label for the pinId and pinName
469
- const latestPin = this.drawing.pins[this.drawing.pins.length - 1];
470
- const [pinId, , angle] = latestPin;
471
- const [, , , endX, endY] = positionParams;
472
-
473
- let pinNameAlignment = HorizontalAlign.Left;
474
- let pinNameOffsetX = 4;
475
-
476
- let pinIdOffsetX = 0;
477
- let pinIdAlignment = HorizontalAlign.Left;
478
-
479
- let pinIdVAlignment = VerticalAlign.Bottom;
480
- let pinIdOffsetY = -2;
481
-
482
- switch (angle) {
483
- case 0:
484
- pinNameAlignment = HorizontalAlign.Left;
485
- pinNameOffsetX = 4;
486
- pinIdAlignment = HorizontalAlign.Right;
487
- pinIdOffsetX = -2;
488
- break;
489
- case 90:
490
- case 180:
491
- pinNameAlignment = HorizontalAlign.Right;
492
- pinNameOffsetX = -4;
493
- pinIdAlignment = HorizontalAlign.Left;
494
- pinIdOffsetX = 2;
495
- break;
496
- case 270:
497
- pinNameAlignment = HorizontalAlign.Left;
498
- pinNameOffsetX = 4;
499
- pinIdAlignment = HorizontalAlign.Left;
500
- pinIdOffsetX = 2;
501
- pinIdOffsetY = 2;
502
- pinIdVAlignment = VerticalAlign.Top;
503
- break;
504
- }
505
-
506
- if (angle === 0 || angle === 90 || angle === 180 || angle === 270) {
507
- const usePinName = pinNameParam ?? "";
508
-
509
- // Draw the pinName
510
- usePinName !== "" && drawing.addLabel(
511
- endX + pinNameOffsetX, endY, usePinName, {
512
- fontSize: 10,
513
- anchor: pinNameAlignment,
514
- vanchor: VerticalAlign.Middle,
515
- });
516
-
517
- // Draw pin Id
518
- displayPinId && drawing.addLabel(
519
- endX + pinIdOffsetX, endY + pinIdOffsetY, pinId.toString(), {
520
- fontSize: 8,
521
- anchor: pinIdAlignment,
522
- vanchor: pinIdVAlignment,
523
- });
524
- }
525
- }
526
-
527
- constructor(drawing: SymbolDrawing) {
528
- super();
529
- this.drawing = drawing;
530
- }
531
- }
532
-
533
- export enum PlaceHolderCommands {
534
- arc = 'arc',
535
- circle = 'circle',
536
- rect = 'rect',
537
- triangle = 'triangle',
538
- pin = 'pin',
539
- hpin = 'hpin',
540
- vpin = 'vpin',
541
- hline = 'hline',
542
- vline = 'vline',
543
- line = 'line',
544
- label = 'label',
545
- path = 'path',
546
- lineWidth = 'lineWidth',
547
- fill = 'fill',
548
- lineColor = 'lineColor'
549
- }
550
-
551
- export class SymbolCustom extends SymbolGraphic {
552
-
553
- pinDefinition: SymbolPinDefintion[] = [];
554
-
555
- bodyWidth = 100;
556
-
557
- pinLength = 20;
558
-
559
- width = 100;
560
- height = 100;
561
-
562
- pinSpacing = 20;
563
-
564
- pinTextPadding = 5;
565
-
566
- pins: SymbolPinLayout[] = [];
567
-
568
- _cacheLeftPins: SymbolPinDefintion[];
569
- _cacheRightPins: SymbolPinDefintion[];
570
-
571
- constructor(pinDefinition: SymbolPinDefintion[]) {
572
- super();
573
-
574
- // define the left and right pins only for now
575
- this.pinDefinition = pinDefinition;
576
- }
577
-
578
- generateDrawing(): void {
579
- // Determine the size based on the definition
580
-
581
- const leftPins = this.pinDefinition.filter(item => {
582
- return item.side === SymbolPinSide.Left;
583
- });
584
-
585
- const rightPins = this.pinDefinition.filter(item => {
586
- return item.side === SymbolPinSide.Right;
587
- });
588
-
589
- const maxLeftPins = Math.max(...leftPins.map(item => item.position)) + 1;
590
- const maxRightPins = Math.max(...rightPins.map(item => item.position)) + 1;
591
-
592
- const drawing = new SymbolDrawing();
593
- drawing.angle = this._angle;
594
-
595
- const bodyWidth = this.bodyWidth;
596
- const bodyHeight = (1 + Math.max(maxLeftPins, maxRightPins)) * this.pinSpacing;
597
-
598
- // drawing.addSetFillColor(bodyColor);
599
-
600
- drawing.addRect(0, 0, bodyWidth, bodyHeight);
601
-
602
- // Setup the pins
603
- const leftPinStart = -bodyWidth / 2;
604
- const rightPinStart = bodyWidth / 2;
605
- const pinStartY = -bodyHeight / 2;
606
-
607
- leftPins.forEach(pin => {
608
- const position = pin.position;
609
- const pinY = pinStartY + (position + 1) * this.pinSpacing // Includes the offset too
610
- drawing.addPin(pin.pinId, leftPinStart - this.pinLength, pinY, leftPinStart, pinY);
611
-
612
- drawing.addLabel(leftPinStart + 4, pinY, pin.text, {
613
- fontSize: 10,
614
- anchor: HorizontalAlign.Left,
615
- vanchor: VerticalAlign.Middle,
616
- });
617
-
618
- // Add the pin number
619
- drawing.addLabel(leftPinStart - 2 , pinY - 2, pin.pinId.toString(), {
620
- fontSize: 8,
621
- anchor: HorizontalAlign.Right,
622
- vanchor: VerticalAlign.Bottom,
623
- });
624
- });
625
-
626
- rightPins.forEach(pin => {
627
- const position = pin.position;
628
- const pinY = pinStartY + (position + 1) * this.pinSpacing // Includes the offset too
629
- drawing.addPin(pin.pinId, rightPinStart + this.pinLength, pinY, rightPinStart, pinY);
630
-
631
- drawing.addLabel(rightPinStart - 4, pinY, pin.text, {
632
- fontSize: 10,
633
- anchor: HorizontalAlign.Right,
634
- vanchor: VerticalAlign.Middle,
635
- });
636
-
637
- // Add the pin number
638
- drawing.addLabel(rightPinStart + 2 , pinY - 2, pin.pinId.toString(), {
639
- fontSize: 8,
640
- anchor: HorizontalAlign.Left,
641
- vanchor: VerticalAlign.Bottom,
642
- });
643
- });
644
-
645
- const instanceName = this.getLabelValue("refdes");
646
- instanceName && drawing.addLabel(-bodyWidth/2, -bodyHeight/2 - 4, instanceName, {
647
- fontSize: 10,
648
- anchor: HorizontalAlign.Left,
649
- });
650
-
651
- const acceptedMPNKeys = ['MPN', 'mpn', 'manufacturer_pn'];
652
-
653
- acceptedMPNKeys.some(key => {
654
- const labelValue = this.getLabelValue(key);
655
- if (labelValue !== undefined){
656
- drawing.addLabel(-bodyWidth/2, bodyHeight/2 + 4, labelValue, {
657
- fontSize: 10,
658
- anchor: HorizontalAlign.Left,
659
- vanchor: VerticalAlign.Top,
660
- });
661
- }
662
- });
663
-
664
- this.drawing = drawing;
665
- this._cacheLeftPins = leftPins;
666
- this._cacheRightPins = rightPins;
667
- }
668
-
669
- calculateSize(): void {
670
- // This width also includes the pin length
671
- this.width = this.bodyWidth + 2 * this.pinLength;
672
- this.height = (1 + Math.max(this._cacheLeftPins.length,
673
- this._cacheRightPins.length)) * this.pinSpacing;
674
- }
675
-
676
- }
677
-
678
-
679
- export class SymbolDrawing {
680
-
681
- items: (Feature | GeometryProp)[] = [];
682
-
683
- // pinId, feature, angle
684
- pins: [number, Feature, number][] = [];
685
-
686
- angle = 0;
687
-
688
- mainOrigin:[number, number] = [0, 0];
689
-
690
- logger: Logger = null;
691
-
692
- clear(): void {
693
- this.items = [];
694
- this.pins = [];
695
- }
696
-
697
- log(...params: any[]): void {
698
- this.logger && this.logger.add(params.join(' '));
699
- }
700
-
701
- addLine(startX: number, startY: number, endX: number, endY: number): SymbolDrawing {
702
- this.items.push(
703
- Geometry.segment([startX, startY], [endX, endY])
704
- );
705
-
706
- return this;
707
- }
708
-
709
- addPin(pinId: number, startX: number, startY: number,
710
- endX: number, endY: number): SymbolDrawing {
711
-
712
- // Determine the pin angle based on vector with start point
713
- // going to end point. The angle is relative to the x-axis.
714
- // 270
715
- // 180 -- start --> 0
716
- // 90
717
-
718
- let angle = 0;
719
- if (startX === endX) {
720
- if (startY > endY) {
721
- angle = 270;
722
- } else if (startY < endY) {
723
- angle = 90;
724
- }
725
- } else {
726
- if (startX < endX) {
727
- angle = 0;
728
- } else if (startX > endX) {
729
- angle = 180;
730
- }
731
- }
732
-
733
- this.pins.push([
734
- pinId,
735
- Geometry.segment([startX, startY], [endX, endY]),
736
- angle
737
- ]);
738
-
739
- return this;
740
- }
741
-
742
- addVLine(startX: number, startY: number, value: number): SymbolDrawing {
743
- this.items.push(
744
- Geometry.segment([startX, startY], [startX, startY + value])
745
- );
746
- return this;
747
- }
748
-
749
- addHLine(startX: number, startY: number, value: number): SymbolDrawing {
750
- this.items.push(
751
- Geometry.segment([startX, startY], [startX + value, startY])
752
- );
753
- return this;
754
- }
755
-
756
- addRect(centerX: number, centerY: number,width: number, height: number): SymbolDrawing {
757
- const width2 = width/2;
758
- const height2 = height/2;
759
-
760
- this.items.push(
761
- Geometry.polygon([
762
- [centerX - width2, centerY - height2],
763
- [centerX + width2, centerY - height2],
764
- [centerX + width2, centerY + height2],
765
- [centerX - width2, centerY + height2],
766
- [centerX - width2, centerY - height2]
767
- ])
768
- );
769
-
770
- return this;
771
- }
772
-
773
- addTriangle(startX: number, startY: number, endX: number, endY: number, width: number): SymbolDrawing {
774
- const line = Geometry.line(
775
- startX, startY,
776
- endX, endY);
777
-
778
- const normLine = line.norm;
779
- const dx1 = normLine.x * width / 2;
780
- const dy1 = normLine.y * width / 2;
781
- const dx2 = normLine.x * -width / 2;
782
- const dy2 = normLine.y * -width / 2;
783
-
784
- this.items.push(
785
- Geometry.polygon([
786
- [dx1 + startX, dy1 + startY],
787
- [dx2 + startX, dy2 + startY],
788
- [endX, endY],
789
- [dx1 + startX, dy1 + startY],
790
- ])
791
- );
792
-
793
- return this;
794
- }
795
-
796
- addRect2(x: number, y: number, x2: number, y2: number): SymbolDrawing {
797
- this.items.push(
798
- Geometry.polygon([
799
- [x, y],
800
- [x2, y],
801
- [x2, y2],
802
- [x, y2],
803
- [x, y]
804
- ])
805
- );
806
-
807
- return this;
808
- }
809
-
810
- addLabel(x: number, y: number, textValue: string, style: LabelStyle): SymbolDrawing {
811
- this.items.push(
812
- Geometry.label(null, x, y, textValue, style)
813
- )
814
-
815
- return this;
816
- }
817
-
818
- addLabelId(id: string, x: number, y: number, textValue: string, style: LabelStyle,): SymbolDrawing {
819
- this.items.push(
820
- Geometry.label(id, x, y, textValue, style)
821
- )
822
-
823
- return this;
824
- }
825
-
826
- addPath(...pathParts:any): SymbolDrawing {
827
- const parts = pathParts.reduce((accum, tmp) => {
828
- if (typeof tmp === "string"){
829
- accum = accum.concat(tmp.split(" "));
830
- } else if (typeof tmp === "number"){
831
- accum.push(tmp);
832
- }
833
- return accum;
834
- }, [] as (number|string)[]);
835
-
836
- const geomObjects = [];
837
- let currentObj: [x: number, y: number][] = null;
838
-
839
- for (let i = 0; i < parts.length; i++) {
840
- const command = parts[i];
841
- if (command === 'M') {
842
- // Start a new object
843
- if (currentObj !== null) {
844
- geomObjects.push(currentObj);
845
- }
846
-
847
- const x = Number(parts[i + 1]);
848
- const y = Number(parts[i + 2]);
849
-
850
- currentObj = [[x, y]];
851
-
852
- i += 2;
853
-
854
- } else if (command === 'L') {
855
- const x = Number(parts[i + 1]);
856
- const y = Number(parts[i + 2]);
857
- currentObj.push([x, y]);
858
-
859
- i += 2;
860
-
861
- } else if (command === 'Z'){
862
- // Return back to first point in path
863
- const firstPoint = currentObj[0];
864
- currentObj.push(firstPoint);
865
- }
866
- }
867
-
868
- if (currentObj !== null){
869
- geomObjects.push(currentObj);
870
- currentObj = null;
871
- }
872
-
873
- geomObjects.forEach(coords => {
874
- const [first] = coords;
875
- const last = coords[coords.length - 1];
876
-
877
- if (first[0] === last[0] && first[1] === last[1]){
878
- // If both are the same, then this is a polygon
879
- this.items.push(Geometry.polygon(coords));
880
- } else {
881
- this.items.push(Geometry.multiline(coords));
882
- }
883
- })
884
-
885
- return this;
886
- }
887
-
888
- addSetLineWidth(value: number): SymbolDrawing {
889
- this.items.push(new GeometryProp('lineWidth', value));
890
- return this;
891
- }
892
-
893
- addSetLineColor(value: string): SymbolDrawing {
894
- this.items.push(new GeometryProp('lineColor', value));
895
- return this;
896
- }
897
-
898
- addSetFillColor(value: string): SymbolDrawing {
899
- this.items.push(new GeometryProp('fillColor', value));
900
- return this;
901
- }
902
-
903
- addArc(x: number, y: number, radius: number,
904
- startAngle: number, endAngle: number): SymbolDrawing {
905
-
906
- // Angles in degrees, convert to radians
907
- startAngle = startAngle * Math.PI / 180;
908
- endAngle = endAngle * Math.PI / 180;
909
-
910
- this.items.push(
911
- Geometry.arc([x, y], radius, startAngle, endAngle, true));
912
-
913
- return this;
914
- }
915
-
916
- getPaths(): {path: string,
917
- fillColor: string,
918
- lineColor: string,
919
- lineWidth: number}[] {
920
-
921
- let currentFill = "#fff";
922
- let currentLineWidth = 1;
923
- let currentLineColor = '#333';
924
-
925
- const pathItems = [];
926
-
927
- this.items.forEach(item => {
928
- if (!(item instanceof Label)){
929
- if (item instanceof GeometryProp){
930
- if (item.name === 'lineWidth'){
931
- currentLineWidth = item.value as number;
932
- } else if (item.name === 'lineColor'){
933
- currentLineColor = item.value as string;
934
- } else if (item.name === 'fillColor'){
935
- currentFill = item.value as string;
936
- }
937
- } else {
938
- const rotatedPath = Geometry.groupRotate([item], this.angle,
939
- this.mainOrigin);
940
-
941
- const {path, isClosedPolygon} =
942
- this.featuresToPath(rotatedPath);
943
-
944
- pathItems.push({
945
- path: path,
946
- lineWidth: currentLineWidth,
947
- lineColor: currentLineColor,
948
- fillColor: isClosedPolygon ? currentFill : 'none',
949
- });
950
- }
951
- }
952
- });
953
-
954
- return pathItems;
955
- }
956
-
957
- getPinsPath(): string {
958
- const features = this.pins.map(item => item[1]);
959
- const withAngle = Geometry.groupRotate(features, this.angle, this.mainOrigin);
960
- const { path } = this.featuresToPath(withAngle);
961
- return path;
962
- }
963
-
964
- getLabels(): Label[] {
965
- return this.items.filter(item => item instanceof Label) as Label[];
966
- }
967
-
968
- private featuresToPath(items: Feature[]):
969
- {path: string, isClosedPolygon: boolean} {
970
- return Geometry.featuresToPath(items);
971
- }
972
-
973
- getBoundingBox(excludeLabels = false): {
974
- width: number, height: number,
975
- start: SimplePoint, end: SimplePoint
976
- } {
977
- // If excludeLabels is true, then do not add labels to the list
978
- // of items to measure the boundaries.
979
-
980
- const pinFeatures = this.pins.map(pin => {
981
- return pin[1];
982
- });
983
-
984
- const drawingFeatures = this.items.reduce((accum, item) => {
985
- if (!excludeLabels || (excludeLabels && !(item instanceof Label))){
986
- if (!(item instanceof GeometryProp)){
987
- accum.push(item);
988
- }
989
- }
990
-
991
- return accum;
992
-
993
- }, [] as Feature[]);
994
-
995
- const measureItems = [...drawingFeatures, ...pinFeatures];
996
-
997
- const withAngle = Geometry.groupRotate(measureItems, this.angle, this.mainOrigin);
998
-
999
- return Geometry.groupBounds(withAngle);
1000
- }
1001
-
1002
- getPinPosition(pinId: number): { start: [number, number], end: [number, number], angle: number } {
1003
- const pin = this.pins.find(item => {
1004
- return item[0] === pinId;
1005
- });
1006
-
1007
- if (pin) {
1008
- const [pinId, feature, angle] = pin;
1009
-
1010
- // Apply angle to feature
1011
-
1012
- const withAngle = Geometry.rotateDegs(feature, this.angle, this.mainOrigin);
1013
- const coords = Geometry.getCoords(withAngle);
1014
-
1015
- return {
1016
- start: coords[0],
1017
- end: coords[1],
1018
- angle,
1019
- }
1020
- }
1021
- }
1022
- }
1023
-
1024
- export type SubExpressionCommand = [commandName: string,
1025
- positionParams: any[],
1026
- keywordParams: Map<string, any>];
1027
-
1028
- export class SymbolDrawingCommands extends SymbolDrawing {
1029
-
1030
- id = "";
1031
- private commands: SubExpressionCommand[];
1032
-
1033
- constructor(commands: SubExpressionCommand[]){
1034
- super();
1035
- this.commands = commands;
1036
- this.id = Math.random().toString().slice(2);
1037
- }
1038
-
1039
- getCommands(): SubExpressionCommand[] {
1040
- return this.commands;
1041
- }
1042
-
1043
- clone(): SymbolDrawingCommands {
1044
- // Force a deep clone
1045
- const tmpCommands: SubExpressionCommand[] = this.commands.map(item => {
1046
- if (item[0] === PlaceHolderCommands.label) {
1047
- const commandName = item[0];
1048
- const positionParams = item[1];
1049
- const keywordParams = item[2];
1050
-
1051
- const newMap = new Map<string, any>();
1052
- for (const [key, value] of keywordParams) {
1053
- newMap.set(key, value);
1054
- }
1055
-
1056
- return [commandName, positionParams, newMap];
1057
- } else {
1058
- return [...item];
1059
- }
1060
- });
1061
- return new SymbolDrawingCommands(tmpCommands);
1062
- }
1063
- }
1064
-
1065
- type SimplePoint = [x: number, y: number];
1066
-
1067
- type SymbolPinLayout = {
1068
- pinId: number,
1069
- angle: number,
1070
- text: string,
1071
- start: {
1072
- x: number, y: number
1073
- },
1074
- end: {
1075
- x: number, y: number
1076
- }
1077
- }
1078
-
1079
- export type SymbolPinDefintion = {
1080
- side: string,
1081
- pinId: number,
1082
- text: string, // Display value at the pin
1083
- position: number,
1084
- }
1085
-