circuit-to-canvas 0.0.46 → 0.0.47

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,7 @@
1
1
  import { expect, test } from "bun:test"
2
2
  import { createCanvas } from "@napi-rs/canvas"
3
3
  import { CircuitToCanvasDrawer } from "../../lib/drawer"
4
+ import type { AnyCircuitElement } from "circuit-json"
4
5
 
5
6
  /**
6
7
  * Comprehensive test for soldermask margin functionality:
@@ -9,23 +10,89 @@ import { CircuitToCanvasDrawer } from "../../lib/drawer"
9
10
  * - Row 3: Negative margin (soldermask_margin = -0.3)
10
11
  * - Row 4: Default behavior (no margin specified)
11
12
  *
12
- * Tests different element types: SMT pads, plated holes, and holes
13
+ * Columns (left to right):
14
+ * SMT Pads:
15
+ * 1. Rotated Rect
16
+ * 2. Polygon
17
+ * 3. Pill
18
+ * 4. Rotated Pill
19
+ * 5. Circle
20
+ * 6. Rect
21
+ * Plated Holes:
22
+ * 7. Circle PTH
23
+ * 8. Oval PTH
24
+ * 9. Pill PTH
25
+ * 10. Circ+Rect PTH (circular_hole_with_rect_pad)
26
+ * 11. Pill+Rect PTH (pill_hole_with_rect_pad)
27
+ * 12. RotPill+Rect PTH (rotated_pill_hole_with_rect_pad)
28
+ * 13. Poly Pad PTH (hole_with_polygon_pad)
29
+ * Non-plated Holes:
30
+ * 14. Circle Hole
31
+ * 15. Oval Hole
32
+ * 16. Pill Hole
13
33
  */
14
34
  test("comprehensive soldermask margin test", async () => {
15
- const canvas = createCanvas(1200, 1000)
35
+ const canvas = createCanvas(1800, 1000)
16
36
  const ctx = canvas.getContext("2d")
17
37
  const drawer = new CircuitToCanvasDrawer(ctx)
18
38
 
19
39
  ctx.fillStyle = "#1a1a1a"
20
- ctx.fillRect(0, 0, 1200, 1000)
40
+ ctx.fillRect(0, 0, 2000, 1000)
21
41
 
22
- const circuit: any = [
42
+ // Layout configuration - centered around x: 0
43
+ const colSpacing = 10 // spacing between columns
44
+ const numCols = 16
45
+ const totalWidth = (numCols - 1) * colSpacing
46
+ const startX = -totalWidth / 2 // center the columns
47
+
48
+ // Column X positions (centered around 0)
49
+ const col = {
50
+ // SMT Pads (columns 1-6)
51
+ rotatedRect: startX + 0 * colSpacing,
52
+ polygon: startX + 1 * colSpacing,
53
+ pill: startX + 2 * colSpacing,
54
+ rotatedPill: startX + 3 * colSpacing,
55
+ circlePad: startX + 4 * colSpacing,
56
+ rectPad: startX + 5 * colSpacing,
57
+ // Plated Holes (columns 7-13)
58
+ circlePlatedHole: startX + 6 * colSpacing,
59
+ ovalPlatedHole: startX + 7 * colSpacing,
60
+ pillPlatedHole: startX + 8 * colSpacing,
61
+ circRectPTH: startX + 9 * colSpacing,
62
+ pillRectPTH: startX + 10 * colSpacing,
63
+ rotPillRectPTH: startX + 11 * colSpacing,
64
+ polyPadPTH: startX + 12 * colSpacing,
65
+ // Non-plated Holes (columns 14-16)
66
+ circleHole: startX + 13 * colSpacing,
67
+ ovalHole: startX + 14 * colSpacing,
68
+ pillHole: startX + 15 * colSpacing,
69
+ }
70
+
71
+ // Row Y positions (centered around 0)
72
+ const row = {
73
+ fullyCovered: 12,
74
+ positiveMargin: 4,
75
+ negativeMargin: -4,
76
+ default: -12,
77
+ }
78
+
79
+ // Helper for polygon pad outline (hexagon centered at origin)
80
+ const polyPadOutline = [
81
+ { x: -1, y: -1.5 },
82
+ { x: 1, y: -1.5 },
83
+ { x: 1.5, y: 0 },
84
+ { x: 1, y: 1.5 },
85
+ { x: -1, y: 1.5 },
86
+ { x: -1.5, y: 0 },
87
+ ]
88
+
89
+ const circuit: AnyCircuitElement[] = [
23
90
  {
24
91
  type: "pcb_board",
25
92
  pcb_board_id: "board_test",
26
93
  center: { x: 0, y: 0 },
27
- width: 50,
28
- height: 40,
94
+ width: 180,
95
+ height: 45,
29
96
  thickness: 1.6,
30
97
  num_layers: 2,
31
98
  material: "fr4",
@@ -35,186 +102,921 @@ test("comprehensive soldermask margin test", async () => {
35
102
  type: "pcb_component",
36
103
  pcb_component_id: "dummy_component",
37
104
  center: { x: 0, y: 0 },
38
- width: 50,
39
- height: 40,
105
+ width: 180,
106
+ height: 45,
40
107
  rotation: 0,
41
108
  layer: "top",
42
109
  source_component_id: "dummy",
43
110
  obstructs_within_bounds: false,
44
111
  },
112
+
113
+ // =====================================================
45
114
  // Row 1: Fully covered elements (is_covered_with_solder_mask = true)
115
+ // =====================================================
116
+
117
+ // Column 1: Rotated Rect SMT Pad
118
+ {
119
+ type: "pcb_smtpad",
120
+ pcb_smtpad_id: "pad_fully_covered_rotated_rect",
121
+ shape: "rotated_rect",
122
+ x: col.rotatedRect,
123
+ y: row.fullyCovered,
124
+ width: 2,
125
+ height: 1,
126
+ ccw_rotation: 30,
127
+ layer: "top",
128
+ is_covered_with_solder_mask: true,
129
+ },
130
+ // Column 2: Polygon SMT Pad
131
+ {
132
+ type: "pcb_smtpad",
133
+ pcb_smtpad_id: "pad_fully_covered_polygon",
134
+ shape: "polygon",
135
+ layer: "top",
136
+ points: [
137
+ { x: col.polygon - 1, y: row.fullyCovered - 1 },
138
+ { x: col.polygon + 1, y: row.fullyCovered - 1 },
139
+ { x: col.polygon + 2, y: row.fullyCovered + 1 },
140
+ { x: col.polygon + 1, y: row.fullyCovered + 3 },
141
+ { x: col.polygon - 1, y: row.fullyCovered + 3 },
142
+ { x: col.polygon - 2, y: row.fullyCovered + 1 },
143
+ ],
144
+ is_covered_with_solder_mask: true,
145
+ },
146
+ // Column 3: Pill SMT Pad
147
+ {
148
+ type: "pcb_smtpad",
149
+ pcb_smtpad_id: "pad_fully_covered_pill",
150
+ shape: "pill",
151
+ x: col.pill,
152
+ y: row.fullyCovered,
153
+ width: 3,
154
+ height: 1,
155
+ radius: 0.5,
156
+ layer: "top",
157
+ is_covered_with_solder_mask: true,
158
+ },
159
+ // Column 4: Rotated Pill SMT Pad
160
+ {
161
+ type: "pcb_smtpad",
162
+ pcb_smtpad_id: "pad_fully_covered_rotated_pill",
163
+ shape: "rotated_pill",
164
+ x: col.rotatedPill,
165
+ y: row.fullyCovered,
166
+ width: 3,
167
+ height: 1,
168
+ radius: 0.5,
169
+ ccw_rotation: 30,
170
+ layer: "top",
171
+ is_covered_with_solder_mask: true,
172
+ },
173
+ // Column 5: Circle SMT Pad
46
174
  {
47
175
  type: "pcb_smtpad",
48
- pcb_smtpad_id: "pad_fully_covered_1",
176
+ pcb_smtpad_id: "pad_fully_covered_circle",
49
177
  shape: "circle",
50
- x: -18,
51
- y: 12,
178
+ x: col.circlePad,
179
+ y: row.fullyCovered,
52
180
  radius: 1,
53
181
  layer: "top",
54
182
  is_covered_with_solder_mask: true,
55
183
  },
184
+ // Column 6: Rect SMT Pad
56
185
  {
57
186
  type: "pcb_smtpad",
58
- pcb_smtpad_id: "pad_fully_covered_square",
187
+ pcb_smtpad_id: "pad_fully_covered_rect",
59
188
  shape: "rect",
60
- x: -12,
61
- y: 12,
189
+ x: col.rectPad,
190
+ y: row.fullyCovered,
62
191
  width: 2,
63
192
  height: 2,
64
193
  layer: "top",
65
194
  is_covered_with_solder_mask: true,
66
195
  },
196
+ // Column 7: Circle Plated Hole
67
197
  {
68
198
  type: "pcb_plated_hole",
69
- pcb_plated_hole_id: "hole_fully_covered",
199
+ pcb_plated_hole_id: "hole_fully_covered_circle",
70
200
  shape: "circle",
71
- x: -5,
72
- y: 12,
201
+ x: col.circlePlatedHole,
202
+ y: row.fullyCovered,
73
203
  hole_diameter: 1,
74
204
  outer_diameter: 2,
75
205
  layers: ["top", "bottom"],
76
206
  is_covered_with_solder_mask: true,
77
207
  },
208
+ // Column 8: Oval Plated Hole
209
+ {
210
+ type: "pcb_plated_hole",
211
+ pcb_plated_hole_id: "hole_fully_covered_oval",
212
+ shape: "oval",
213
+ x: col.ovalPlatedHole,
214
+ y: row.fullyCovered,
215
+ outer_width: 3,
216
+ outer_height: 1.5,
217
+ hole_width: 2,
218
+ hole_height: 0.8,
219
+ ccw_rotation: 0,
220
+ layers: ["top", "bottom"],
221
+ is_covered_with_solder_mask: true,
222
+ },
223
+ // Column 9: Pill Plated Hole
224
+ {
225
+ type: "pcb_plated_hole",
226
+ pcb_plated_hole_id: "hole_fully_covered_pill",
227
+ shape: "pill",
228
+ x: col.pillPlatedHole,
229
+ y: row.fullyCovered,
230
+ outer_width: 3,
231
+ outer_height: 1.5,
232
+ hole_width: 2,
233
+ hole_height: 0.8,
234
+ ccw_rotation: 0,
235
+ layers: ["top", "bottom"],
236
+ is_covered_with_solder_mask: true,
237
+ },
238
+ // Column 10: Circular Hole with Rect Pad
239
+ {
240
+ type: "pcb_plated_hole",
241
+ pcb_plated_hole_id: "hole_fully_covered_circ_rect",
242
+ shape: "circular_hole_with_rect_pad",
243
+ x: col.circRectPTH,
244
+ y: row.fullyCovered,
245
+ hole_shape: "circle",
246
+ hole_diameter: 1,
247
+ pad_shape: "rect",
248
+ rect_pad_width: 3,
249
+ rect_pad_height: 2,
250
+ hole_offset_x: 0,
251
+ hole_offset_y: 0,
252
+ layers: ["top", "bottom"],
253
+ is_covered_with_solder_mask: true,
254
+ },
255
+ // Column 11: Pill Hole with Rect Pad
256
+ {
257
+ type: "pcb_plated_hole",
258
+ pcb_plated_hole_id: "hole_fully_covered_pill_rect",
259
+ shape: "pill_hole_with_rect_pad",
260
+ x: col.pillRectPTH,
261
+ y: row.fullyCovered,
262
+ hole_shape: "pill",
263
+ hole_width: 2,
264
+ hole_height: 0.8,
265
+ pad_shape: "rect",
266
+ rect_pad_width: 3,
267
+ rect_pad_height: 2,
268
+ hole_offset_x: 0,
269
+ hole_offset_y: 0,
270
+ layers: ["top", "bottom"],
271
+ is_covered_with_solder_mask: true,
272
+ },
273
+ // Column 12: Rotated Pill Hole with Rect Pad
274
+ {
275
+ type: "pcb_plated_hole",
276
+ pcb_plated_hole_id: "hole_fully_covered_rot_pill_rect",
277
+ shape: "rotated_pill_hole_with_rect_pad",
278
+ x: col.rotPillRectPTH,
279
+ y: row.fullyCovered,
280
+ hole_shape: "rotated_pill",
281
+ hole_width: 2,
282
+ hole_height: 0.8,
283
+ hole_ccw_rotation: 45,
284
+ pad_shape: "rect",
285
+ rect_pad_width: 3,
286
+ rect_pad_height: 2,
287
+ rect_ccw_rotation: 30,
288
+ hole_offset_x: 0,
289
+ hole_offset_y: 0,
290
+ layers: ["top", "bottom"],
291
+ is_covered_with_solder_mask: true,
292
+ },
293
+ // Column 13: Hole with Polygon Pad
294
+ {
295
+ type: "pcb_plated_hole",
296
+ pcb_plated_hole_id: "hole_fully_covered_poly_pad",
297
+ shape: "hole_with_polygon_pad",
298
+ x: col.polyPadPTH,
299
+ y: row.fullyCovered,
300
+ hole_shape: "circle",
301
+ hole_diameter: 0.8,
302
+ hole_offset_x: 0,
303
+ hole_offset_y: 0,
304
+ pad_outline: polyPadOutline,
305
+ layers: ["top", "bottom"],
306
+ is_covered_with_solder_mask: true,
307
+ },
308
+ // Column 14: Circle Hole
78
309
  {
79
310
  type: "pcb_hole",
80
- pcb_hole_id: "np_hole_fully_covered",
311
+ pcb_hole_id: "np_hole_fully_covered_circle",
81
312
  hole_shape: "circle",
82
- x: 5,
83
- y: 12,
313
+ x: col.circleHole,
314
+ y: row.fullyCovered,
84
315
  hole_diameter: 1,
85
316
  is_covered_with_solder_mask: true,
86
317
  },
318
+ // Column 15: Oval Hole
319
+ {
320
+ type: "pcb_hole",
321
+ pcb_hole_id: "np_hole_fully_covered_oval",
322
+ hole_shape: "oval",
323
+ x: col.ovalHole,
324
+ y: row.fullyCovered,
325
+ hole_width: 2,
326
+ hole_height: 1,
327
+ is_covered_with_solder_mask: true,
328
+ },
329
+ // Column 16: Pill Hole
330
+ {
331
+ type: "pcb_hole",
332
+ pcb_hole_id: "np_hole_fully_covered_pill",
333
+ hole_shape: "pill",
334
+ x: col.pillHole,
335
+ y: row.fullyCovered,
336
+ hole_width: 2,
337
+ hole_height: 1,
338
+ is_covered_with_solder_mask: true,
339
+ },
340
+
341
+ // =====================================================
87
342
  // Row 2: Positive margin (soldermask_margin = 0.5)
343
+ // =====================================================
344
+
345
+ // Column 1: Rotated Rect SMT Pad
346
+ {
347
+ type: "pcb_smtpad",
348
+ pcb_smtpad_id: "pad_positive_margin_rotated_rect",
349
+ shape: "rotated_rect",
350
+ x: col.rotatedRect,
351
+ y: row.positiveMargin,
352
+ width: 2,
353
+ height: 1,
354
+ ccw_rotation: 30,
355
+ layer: "top",
356
+ soldermask_margin: 0.5,
357
+ },
358
+ // Column 2: Polygon SMT Pad
359
+ {
360
+ type: "pcb_smtpad",
361
+ pcb_smtpad_id: "pad_positive_margin_polygon",
362
+ shape: "polygon",
363
+ layer: "top",
364
+ points: [
365
+ { x: col.polygon - 1, y: row.positiveMargin - 1 },
366
+ { x: col.polygon + 1, y: row.positiveMargin - 1 },
367
+ { x: col.polygon + 2, y: row.positiveMargin + 1 },
368
+ { x: col.polygon + 1, y: row.positiveMargin + 3 },
369
+ { x: col.polygon - 1, y: row.positiveMargin + 3 },
370
+ { x: col.polygon - 2, y: row.positiveMargin + 1 },
371
+ ],
372
+ soldermask_margin: 0.5,
373
+ },
374
+ // Column 3: Pill SMT Pad
375
+ {
376
+ type: "pcb_smtpad",
377
+ pcb_smtpad_id: "pad_positive_margin_pill",
378
+ shape: "pill",
379
+ x: col.pill,
380
+ y: row.positiveMargin,
381
+ width: 3,
382
+ height: 1,
383
+ radius: 0.5,
384
+ layer: "top",
385
+ soldermask_margin: 0.5,
386
+ },
387
+ // Column 4: Rotated Pill SMT Pad
388
+ {
389
+ type: "pcb_smtpad",
390
+ pcb_smtpad_id: "pad_positive_margin_rotated_pill",
391
+ shape: "rotated_pill",
392
+ x: col.rotatedPill,
393
+ y: row.positiveMargin,
394
+ width: 3,
395
+ height: 1,
396
+ radius: 0.5,
397
+ ccw_rotation: 30,
398
+ layer: "top",
399
+ soldermask_margin: 0.5,
400
+ },
401
+ // Column 5: Circle SMT Pad
88
402
  {
89
403
  type: "pcb_smtpad",
90
- pcb_smtpad_id: "pad_positive_margin_1",
404
+ pcb_smtpad_id: "pad_positive_margin_circle",
91
405
  shape: "circle",
92
- x: -18,
93
- y: 4,
406
+ x: col.circlePad,
407
+ y: row.positiveMargin,
94
408
  radius: 1,
95
409
  layer: "top",
96
410
  soldermask_margin: 0.5,
97
411
  },
412
+ // Column 6: Rect SMT Pad
98
413
  {
99
414
  type: "pcb_smtpad",
100
- pcb_smtpad_id: "pad_positive_margin_square",
415
+ pcb_smtpad_id: "pad_positive_margin_rect",
101
416
  shape: "rect",
102
- x: -12,
103
- y: 4,
417
+ x: col.rectPad,
418
+ y: row.positiveMargin,
104
419
  width: 2,
105
420
  height: 2,
106
421
  layer: "top",
107
422
  soldermask_margin: 0.5,
108
423
  },
424
+ // Column 7: Circle Plated Hole
109
425
  {
110
426
  type: "pcb_plated_hole",
111
- pcb_plated_hole_id: "hole_positive_margin",
427
+ pcb_plated_hole_id: "hole_positive_margin_circle",
112
428
  shape: "circle",
113
- x: -5,
114
- y: 4,
429
+ x: col.circlePlatedHole,
430
+ y: row.positiveMargin,
115
431
  hole_diameter: 1,
116
432
  outer_diameter: 2,
117
433
  layers: ["top", "bottom"],
118
434
  soldermask_margin: 0.5,
119
435
  },
436
+ // Column 8: Oval Plated Hole
437
+ {
438
+ type: "pcb_plated_hole",
439
+ pcb_plated_hole_id: "hole_positive_margin_oval",
440
+ shape: "oval",
441
+ x: col.ovalPlatedHole,
442
+ y: row.positiveMargin,
443
+ outer_width: 3,
444
+ outer_height: 1.5,
445
+ hole_width: 2,
446
+ hole_height: 0.8,
447
+ ccw_rotation: 0,
448
+ layers: ["top", "bottom"],
449
+ soldermask_margin: 0.5,
450
+ },
451
+ // Column 9: Pill Plated Hole
452
+ {
453
+ type: "pcb_plated_hole",
454
+ pcb_plated_hole_id: "hole_positive_margin_pill",
455
+ shape: "pill",
456
+ x: col.pillPlatedHole,
457
+ y: row.positiveMargin,
458
+ outer_width: 3,
459
+ outer_height: 1.5,
460
+ hole_width: 2,
461
+ hole_height: 0.8,
462
+ ccw_rotation: 0,
463
+ layers: ["top", "bottom"],
464
+ soldermask_margin: 0.5,
465
+ },
466
+ // Column 10: Circular Hole with Rect Pad
467
+ {
468
+ type: "pcb_plated_hole",
469
+ pcb_plated_hole_id: "hole_positive_margin_circ_rect",
470
+ shape: "circular_hole_with_rect_pad",
471
+ x: col.circRectPTH,
472
+ y: row.positiveMargin,
473
+ hole_shape: "circle",
474
+ hole_diameter: 1,
475
+ pad_shape: "rect",
476
+ rect_pad_width: 3,
477
+ rect_pad_height: 2,
478
+ hole_offset_x: 0,
479
+ hole_offset_y: 0,
480
+ layers: ["top", "bottom"],
481
+ soldermask_margin: 0.5,
482
+ },
483
+ // Column 11: Pill Hole with Rect Pad
484
+ {
485
+ type: "pcb_plated_hole",
486
+ pcb_plated_hole_id: "hole_positive_margin_pill_rect",
487
+ shape: "pill_hole_with_rect_pad",
488
+ x: col.pillRectPTH,
489
+ y: row.positiveMargin,
490
+ hole_shape: "pill",
491
+ hole_width: 2,
492
+ hole_height: 0.8,
493
+ pad_shape: "rect",
494
+ rect_pad_width: 3,
495
+ rect_pad_height: 2,
496
+ hole_offset_x: 0,
497
+ hole_offset_y: 0,
498
+ layers: ["top", "bottom"],
499
+ soldermask_margin: 0.5,
500
+ },
501
+ // Column 12: Rotated Pill Hole with Rect Pad
502
+ {
503
+ type: "pcb_plated_hole",
504
+ pcb_plated_hole_id: "hole_positive_margin_rot_pill_rect",
505
+ shape: "rotated_pill_hole_with_rect_pad",
506
+ x: col.rotPillRectPTH,
507
+ y: row.positiveMargin,
508
+ hole_shape: "rotated_pill",
509
+ hole_width: 2,
510
+ hole_height: 0.8,
511
+ hole_ccw_rotation: 45,
512
+ pad_shape: "rect",
513
+ rect_pad_width: 3,
514
+ rect_pad_height: 2,
515
+ rect_ccw_rotation: 30,
516
+ hole_offset_x: 0,
517
+ hole_offset_y: 0,
518
+ layers: ["top", "bottom"],
519
+ soldermask_margin: 0.5,
520
+ },
521
+ // Column 13: Hole with Polygon Pad
522
+ {
523
+ type: "pcb_plated_hole",
524
+ pcb_plated_hole_id: "hole_positive_margin_poly_pad",
525
+ shape: "hole_with_polygon_pad",
526
+ x: col.polyPadPTH,
527
+ y: row.positiveMargin,
528
+ hole_shape: "circle",
529
+ hole_diameter: 0.8,
530
+ hole_offset_x: 0,
531
+ hole_offset_y: 0,
532
+ pad_outline: polyPadOutline,
533
+ layers: ["top", "bottom"],
534
+ soldermask_margin: 0.5,
535
+ },
536
+ // Column 14: Circle Hole
120
537
  {
121
538
  type: "pcb_hole",
122
- pcb_hole_id: "np_hole_positive_margin",
539
+ pcb_hole_id: "np_hole_positive_margin_circle",
123
540
  hole_shape: "circle",
124
- x: 5,
125
- y: 4,
541
+ x: col.circleHole,
542
+ y: row.positiveMargin,
126
543
  hole_diameter: 1,
127
544
  soldermask_margin: 0.5,
128
545
  },
546
+ // Column 15: Oval Hole
547
+ {
548
+ type: "pcb_hole",
549
+ pcb_hole_id: "np_hole_positive_margin_oval",
550
+ hole_shape: "oval",
551
+ x: col.ovalHole,
552
+ y: row.positiveMargin,
553
+ hole_width: 2,
554
+ hole_height: 1,
555
+ soldermask_margin: 0.5,
556
+ },
557
+ // Column 16: Pill Hole
558
+ {
559
+ type: "pcb_hole",
560
+ pcb_hole_id: "np_hole_positive_margin_pill",
561
+ hole_shape: "pill",
562
+ x: col.pillHole,
563
+ y: row.positiveMargin,
564
+ hole_width: 2,
565
+ hole_height: 1,
566
+ soldermask_margin: 0.5,
567
+ },
568
+
569
+ // =====================================================
129
570
  // Row 3: Negative margin (soldermask_margin = -0.3)
571
+ // =====================================================
572
+
573
+ // Column 1: Rotated Rect SMT Pad
130
574
  {
131
575
  type: "pcb_smtpad",
132
- pcb_smtpad_id: "pad_negative_margin_1",
576
+ pcb_smtpad_id: "pad_negative_margin_rotated_rect",
577
+ shape: "rotated_rect",
578
+ x: col.rotatedRect,
579
+ y: row.negativeMargin,
580
+ width: 2,
581
+ height: 1,
582
+ ccw_rotation: 30,
583
+ layer: "top",
584
+ soldermask_margin: -0.3,
585
+ },
586
+ // Column 2: Polygon SMT Pad
587
+ {
588
+ type: "pcb_smtpad",
589
+ pcb_smtpad_id: "pad_negative_margin_polygon",
590
+ shape: "polygon",
591
+ layer: "top",
592
+ points: [
593
+ { x: col.polygon - 1, y: row.negativeMargin - 1 },
594
+ { x: col.polygon + 1, y: row.negativeMargin - 1 },
595
+ { x: col.polygon + 2, y: row.negativeMargin + 1 },
596
+ { x: col.polygon + 1, y: row.negativeMargin + 3 },
597
+ { x: col.polygon - 1, y: row.negativeMargin + 3 },
598
+ { x: col.polygon - 2, y: row.negativeMargin + 1 },
599
+ ],
600
+ soldermask_margin: -0.3,
601
+ },
602
+ // Column 3: Pill SMT Pad
603
+ {
604
+ type: "pcb_smtpad",
605
+ pcb_smtpad_id: "pad_negative_margin_pill",
606
+ shape: "pill",
607
+ x: col.pill,
608
+ y: row.negativeMargin,
609
+ width: 3,
610
+ height: 1,
611
+ radius: 0.5,
612
+ layer: "top",
613
+ soldermask_margin: -0.3,
614
+ },
615
+ // Column 4: Rotated Pill SMT Pad
616
+ {
617
+ type: "pcb_smtpad",
618
+ pcb_smtpad_id: "pad_negative_margin_rotated_pill",
619
+ shape: "rotated_pill",
620
+ x: col.rotatedPill,
621
+ y: row.negativeMargin,
622
+ width: 3,
623
+ height: 1,
624
+ radius: 0.5,
625
+ ccw_rotation: 30,
626
+ layer: "top",
627
+ soldermask_margin: -0.3,
628
+ },
629
+ // Column 5: Circle SMT Pad
630
+ {
631
+ type: "pcb_smtpad",
632
+ pcb_smtpad_id: "pad_negative_margin_circle",
133
633
  shape: "circle",
134
- x: -18,
135
- y: -4,
634
+ x: col.circlePad,
635
+ y: row.negativeMargin,
136
636
  radius: 1,
137
637
  layer: "top",
138
638
  soldermask_margin: -0.3,
139
639
  },
640
+ // Column 6: Rect SMT Pad
140
641
  {
141
642
  type: "pcb_smtpad",
142
- pcb_smtpad_id: "pad_negative_margin_square",
643
+ pcb_smtpad_id: "pad_negative_margin_rect",
143
644
  shape: "rect",
144
- x: -12,
145
- y: -4,
645
+ x: col.rectPad,
646
+ y: row.negativeMargin,
146
647
  width: 2,
147
648
  height: 2,
148
649
  layer: "top",
149
650
  soldermask_margin: -0.3,
150
651
  },
652
+ // Column 7: Circle Plated Hole
151
653
  {
152
654
  type: "pcb_plated_hole",
153
- pcb_plated_hole_id: "hole_negative_margin",
655
+ pcb_plated_hole_id: "hole_negative_margin_circle",
154
656
  shape: "circle",
155
- x: -5,
156
- y: -4,
657
+ x: col.circlePlatedHole,
658
+ y: row.negativeMargin,
157
659
  hole_diameter: 1,
158
660
  outer_diameter: 2,
159
661
  layers: ["top", "bottom"],
160
662
  soldermask_margin: -0.3,
161
663
  },
664
+ // Column 8: Oval Plated Hole
665
+ {
666
+ type: "pcb_plated_hole",
667
+ pcb_plated_hole_id: "hole_negative_margin_oval",
668
+ shape: "oval",
669
+ x: col.ovalPlatedHole,
670
+ y: row.negativeMargin,
671
+ outer_width: 3,
672
+ outer_height: 1.5,
673
+ hole_width: 2,
674
+ hole_height: 0.8,
675
+ ccw_rotation: 0,
676
+ layers: ["top", "bottom"],
677
+ soldermask_margin: -0.3,
678
+ },
679
+ // Column 9: Pill Plated Hole
680
+ {
681
+ type: "pcb_plated_hole",
682
+ pcb_plated_hole_id: "hole_negative_margin_pill",
683
+ shape: "pill",
684
+ x: col.pillPlatedHole,
685
+ y: row.negativeMargin,
686
+ outer_width: 3,
687
+ outer_height: 1.5,
688
+ hole_width: 2,
689
+ hole_height: 0.8,
690
+ ccw_rotation: 0,
691
+ layers: ["top", "bottom"],
692
+ soldermask_margin: -0.3,
693
+ },
694
+ // Column 10: Circular Hole with Rect Pad
695
+ {
696
+ type: "pcb_plated_hole",
697
+ pcb_plated_hole_id: "hole_negative_margin_circ_rect",
698
+ shape: "circular_hole_with_rect_pad",
699
+ x: col.circRectPTH,
700
+ y: row.negativeMargin,
701
+ hole_shape: "circle",
702
+ hole_diameter: 1,
703
+ pad_shape: "rect",
704
+ rect_pad_width: 3,
705
+ rect_pad_height: 2,
706
+ hole_offset_x: 0,
707
+ hole_offset_y: 0,
708
+ layers: ["top", "bottom"],
709
+ soldermask_margin: -0.3,
710
+ },
711
+ // Column 11: Pill Hole with Rect Pad
712
+ {
713
+ type: "pcb_plated_hole",
714
+ pcb_plated_hole_id: "hole_negative_margin_pill_rect",
715
+ shape: "pill_hole_with_rect_pad",
716
+ x: col.pillRectPTH,
717
+ y: row.negativeMargin,
718
+ hole_shape: "pill",
719
+ hole_width: 2,
720
+ hole_height: 0.8,
721
+ pad_shape: "rect",
722
+ rect_pad_width: 3,
723
+ rect_pad_height: 2,
724
+ hole_offset_x: 0,
725
+ hole_offset_y: 0,
726
+ layers: ["top", "bottom"],
727
+ soldermask_margin: -0.3,
728
+ },
729
+ // Column 12: Rotated Pill Hole with Rect Pad
730
+ {
731
+ type: "pcb_plated_hole",
732
+ pcb_plated_hole_id: "hole_negative_margin_rot_pill_rect",
733
+ shape: "rotated_pill_hole_with_rect_pad",
734
+ x: col.rotPillRectPTH,
735
+ y: row.negativeMargin,
736
+ hole_shape: "rotated_pill",
737
+ hole_width: 2,
738
+ hole_height: 0.8,
739
+ hole_ccw_rotation: 45,
740
+ pad_shape: "rect",
741
+ rect_pad_width: 3,
742
+ rect_pad_height: 2,
743
+ rect_ccw_rotation: 30,
744
+ hole_offset_x: 0,
745
+ hole_offset_y: 0,
746
+ layers: ["top", "bottom"],
747
+ soldermask_margin: -0.3,
748
+ },
749
+ // Column 13: Hole with Polygon Pad
750
+ {
751
+ type: "pcb_plated_hole",
752
+ pcb_plated_hole_id: "hole_negative_margin_poly_pad",
753
+ shape: "hole_with_polygon_pad",
754
+ x: col.polyPadPTH,
755
+ y: row.negativeMargin,
756
+ hole_shape: "circle",
757
+ hole_diameter: 0.8,
758
+ hole_offset_x: 0,
759
+ hole_offset_y: 0,
760
+ pad_outline: polyPadOutline,
761
+ layers: ["top", "bottom"],
762
+ soldermask_margin: -0.3,
763
+ },
764
+ // Column 14: Circle Hole
162
765
  {
163
766
  type: "pcb_hole",
164
- pcb_hole_id: "np_hole_negative_margin",
767
+ pcb_hole_id: "np_hole_negative_margin_circle",
165
768
  hole_shape: "circle",
166
- x: 5,
167
- y: -4,
769
+ x: col.circleHole,
770
+ y: row.negativeMargin,
168
771
  hole_diameter: 1,
169
772
  soldermask_margin: -0.3,
170
773
  },
774
+ // Column 15: Oval Hole
775
+ {
776
+ type: "pcb_hole",
777
+ pcb_hole_id: "np_hole_negative_margin_oval",
778
+ hole_shape: "oval",
779
+ x: col.ovalHole,
780
+ y: row.negativeMargin,
781
+ hole_width: 2,
782
+ hole_height: 1,
783
+ soldermask_margin: -0.3,
784
+ },
785
+ // Column 16: Pill Hole
786
+ {
787
+ type: "pcb_hole",
788
+ pcb_hole_id: "np_hole_negative_margin_pill",
789
+ hole_shape: "pill",
790
+ x: col.pillHole,
791
+ y: row.negativeMargin,
792
+ hole_width: 2,
793
+ hole_height: 1,
794
+ soldermask_margin: -0.3,
795
+ },
796
+
797
+ // =====================================================
171
798
  // Row 4: Default behavior (no margin specified)
799
+ // =====================================================
800
+
801
+ // Column 1: Rotated Rect SMT Pad
802
+ {
803
+ type: "pcb_smtpad",
804
+ pcb_smtpad_id: "pad_default_rotated_rect",
805
+ shape: "rotated_rect",
806
+ x: col.rotatedRect,
807
+ y: row.default,
808
+ width: 2,
809
+ height: 1,
810
+ ccw_rotation: 30,
811
+ layer: "top",
812
+ },
813
+ // Column 2: Polygon SMT Pad
814
+ {
815
+ type: "pcb_smtpad",
816
+ pcb_smtpad_id: "pad_default_polygon",
817
+ shape: "polygon",
818
+ layer: "top",
819
+ points: [
820
+ { x: col.polygon - 1, y: row.default - 1 },
821
+ { x: col.polygon + 1, y: row.default - 1 },
822
+ { x: col.polygon + 2, y: row.default + 1 },
823
+ { x: col.polygon + 1, y: row.default + 3 },
824
+ { x: col.polygon - 1, y: row.default + 3 },
825
+ { x: col.polygon - 2, y: row.default + 1 },
826
+ ],
827
+ },
828
+ // Column 3: Pill SMT Pad
829
+ {
830
+ type: "pcb_smtpad",
831
+ pcb_smtpad_id: "pad_default_pill",
832
+ shape: "pill",
833
+ x: col.pill,
834
+ y: row.default,
835
+ width: 3,
836
+ height: 1,
837
+ radius: 0.5,
838
+ layer: "top",
839
+ },
840
+ // Column 4: Rotated Pill SMT Pad
172
841
  {
173
842
  type: "pcb_smtpad",
174
- pcb_smtpad_id: "pad_default_1",
843
+ pcb_smtpad_id: "pad_default_rotated_pill",
844
+ shape: "rotated_pill",
845
+ x: col.rotatedPill,
846
+ y: row.default,
847
+ width: 3,
848
+ height: 1,
849
+ radius: 0.5,
850
+ ccw_rotation: 30,
851
+ layer: "top",
852
+ },
853
+ // Column 5: Circle SMT Pad
854
+ {
855
+ type: "pcb_smtpad",
856
+ pcb_smtpad_id: "pad_default_circle",
175
857
  shape: "circle",
176
- x: -18,
177
- y: -12,
858
+ x: col.circlePad,
859
+ y: row.default,
178
860
  radius: 1,
179
861
  layer: "top",
180
862
  },
863
+ // Column 6: Rect SMT Pad
181
864
  {
182
865
  type: "pcb_smtpad",
183
- pcb_smtpad_id: "pad_default_square",
866
+ pcb_smtpad_id: "pad_default_rect",
184
867
  shape: "rect",
185
- x: -12,
186
- y: -12,
868
+ x: col.rectPad,
869
+ y: row.default,
187
870
  width: 2,
188
871
  height: 2,
189
872
  layer: "top",
190
873
  },
874
+ // Column 7: Circle Plated Hole
191
875
  {
192
876
  type: "pcb_plated_hole",
193
- pcb_plated_hole_id: "hole_default",
877
+ pcb_plated_hole_id: "hole_default_circle",
194
878
  shape: "circle",
195
- x: -5,
196
- y: -12,
879
+ x: col.circlePlatedHole,
880
+ y: row.default,
197
881
  hole_diameter: 1,
198
882
  outer_diameter: 2,
199
883
  layers: ["top", "bottom"],
200
884
  },
885
+ // Column 8: Oval Plated Hole
886
+ {
887
+ type: "pcb_plated_hole",
888
+ pcb_plated_hole_id: "hole_default_oval",
889
+ shape: "oval",
890
+ x: col.ovalPlatedHole,
891
+ y: row.default,
892
+ outer_width: 3,
893
+ outer_height: 1.5,
894
+ hole_width: 2,
895
+ hole_height: 0.8,
896
+ ccw_rotation: 0,
897
+ layers: ["top", "bottom"],
898
+ },
899
+ // Column 9: Pill Plated Hole
900
+ {
901
+ type: "pcb_plated_hole",
902
+ pcb_plated_hole_id: "hole_default_pill",
903
+ shape: "pill",
904
+ x: col.pillPlatedHole,
905
+ y: row.default,
906
+ outer_width: 3,
907
+ outer_height: 1.5,
908
+ hole_width: 2,
909
+ hole_height: 0.8,
910
+ ccw_rotation: 0,
911
+ layers: ["top", "bottom"],
912
+ },
913
+ // Column 10: Circular Hole with Rect Pad
914
+ {
915
+ type: "pcb_plated_hole",
916
+ pcb_plated_hole_id: "hole_default_circ_rect",
917
+ shape: "circular_hole_with_rect_pad",
918
+ x: col.circRectPTH,
919
+ y: row.default,
920
+ hole_shape: "circle",
921
+ hole_diameter: 1,
922
+ pad_shape: "rect",
923
+ rect_pad_width: 3,
924
+ rect_pad_height: 2,
925
+ hole_offset_x: 0,
926
+ hole_offset_y: 0,
927
+ layers: ["top", "bottom"],
928
+ },
929
+ // Column 11: Pill Hole with Rect Pad
930
+ {
931
+ type: "pcb_plated_hole",
932
+ pcb_plated_hole_id: "hole_default_pill_rect",
933
+ shape: "pill_hole_with_rect_pad",
934
+ x: col.pillRectPTH,
935
+ y: row.default,
936
+ hole_shape: "pill",
937
+ hole_width: 2,
938
+ hole_height: 0.8,
939
+ pad_shape: "rect",
940
+ rect_pad_width: 3,
941
+ rect_pad_height: 2,
942
+ hole_offset_x: 0,
943
+ hole_offset_y: 0,
944
+ layers: ["top", "bottom"],
945
+ },
946
+ // Column 12: Rotated Pill Hole with Rect Pad
947
+ {
948
+ type: "pcb_plated_hole",
949
+ pcb_plated_hole_id: "hole_default_rot_pill_rect",
950
+ shape: "rotated_pill_hole_with_rect_pad",
951
+ x: col.rotPillRectPTH,
952
+ y: row.default,
953
+ hole_shape: "rotated_pill",
954
+ hole_width: 2,
955
+ hole_height: 0.8,
956
+ hole_ccw_rotation: 45,
957
+ pad_shape: "rect",
958
+ rect_pad_width: 3,
959
+ rect_pad_height: 2,
960
+ rect_ccw_rotation: 30,
961
+ hole_offset_x: 0,
962
+ hole_offset_y: 0,
963
+ layers: ["top", "bottom"],
964
+ },
965
+ // Column 13: Hole with Polygon Pad
966
+ {
967
+ type: "pcb_plated_hole",
968
+ pcb_plated_hole_id: "hole_default_poly_pad",
969
+ shape: "hole_with_polygon_pad",
970
+ x: col.polyPadPTH,
971
+ y: row.default,
972
+ hole_shape: "circle",
973
+ hole_diameter: 0.8,
974
+ hole_offset_x: 0,
975
+ hole_offset_y: 0,
976
+ pad_outline: polyPadOutline,
977
+ layers: ["top", "bottom"],
978
+ },
979
+ // Column 14: Circle Hole
201
980
  {
202
981
  type: "pcb_hole",
203
- pcb_hole_id: "np_hole_default",
982
+ pcb_hole_id: "np_hole_default_circle",
204
983
  hole_shape: "circle",
205
- x: 5,
206
- y: -12,
984
+ x: col.circleHole,
985
+ y: row.default,
207
986
  hole_diameter: 1,
208
987
  },
209
- // Silkscreen labels for each row
988
+ // Column 15: Oval Hole
989
+ {
990
+ type: "pcb_hole",
991
+ pcb_hole_id: "np_hole_default_oval",
992
+ hole_shape: "oval",
993
+ x: col.ovalHole,
994
+ y: row.default,
995
+ hole_width: 2,
996
+ hole_height: 1,
997
+ },
998
+ // Column 16: Pill Hole
999
+ {
1000
+ type: "pcb_hole",
1001
+ pcb_hole_id: "np_hole_default_pill",
1002
+ hole_shape: "pill",
1003
+ x: col.pillHole,
1004
+ y: row.default,
1005
+ hole_width: 2,
1006
+ hole_height: 1,
1007
+ },
1008
+
1009
+ // =====================================================
1010
+ // Row labels (left side)
1011
+ // =====================================================
210
1012
  {
211
1013
  type: "pcb_silkscreen_text",
212
1014
  pcb_silkscreen_text_id: "label_fully_covered",
213
1015
  pcb_component_id: "dummy_component",
214
1016
  text: "FULLY COVERED",
215
1017
  layer: "top",
216
- anchor_position: { x: 15, y: 12 },
217
- anchor_alignment: "center",
1018
+ anchor_position: { x: -90, y: row.fullyCovered },
1019
+ anchor_alignment: "center_left",
218
1020
  font_size: 1,
219
1021
  font: "tscircuit2024",
220
1022
  },
@@ -224,8 +1026,8 @@ test("comprehensive soldermask margin test", async () => {
224
1026
  pcb_component_id: "dummy_component",
225
1027
  text: "POSITIVE MARGIN",
226
1028
  layer: "top",
227
- anchor_position: { x: 15, y: 4 },
228
- anchor_alignment: "center",
1029
+ anchor_position: { x: -90, y: row.positiveMargin },
1030
+ anchor_alignment: "center_left",
229
1031
  font_size: 1,
230
1032
  font: "tscircuit2024",
231
1033
  },
@@ -235,8 +1037,8 @@ test("comprehensive soldermask margin test", async () => {
235
1037
  pcb_component_id: "dummy_component",
236
1038
  text: "NEGATIVE MARGIN",
237
1039
  layer: "top",
238
- anchor_position: { x: 15, y: -4 },
239
- anchor_alignment: "center",
1040
+ anchor_position: { x: -90, y: row.negativeMargin },
1041
+ anchor_alignment: "center_left",
240
1042
  font_size: 1,
241
1043
  font: "tscircuit2024",
242
1044
  },
@@ -246,12 +1048,15 @@ test("comprehensive soldermask margin test", async () => {
246
1048
  pcb_component_id: "dummy_component",
247
1049
  text: "DEFAULT",
248
1050
  layer: "top",
249
- anchor_position: { x: 15, y: -12 },
250
- anchor_alignment: "center",
1051
+ anchor_position: { x: -90, y: row.default },
1052
+ anchor_alignment: "center_left",
251
1053
  font_size: 1,
252
1054
  font: "tscircuit2024",
253
1055
  },
254
- // Silkscreen lines separating rows
1056
+
1057
+ // =====================================================
1058
+ // Row separators
1059
+ // =====================================================
255
1060
  {
256
1061
  type: "pcb_silkscreen_path",
257
1062
  pcb_silkscreen_path_id: "separator_1",
@@ -259,8 +1064,8 @@ test("comprehensive soldermask margin test", async () => {
259
1064
  layer: "top",
260
1065
  stroke_width: 0.1,
261
1066
  route: [
262
- { x: -25, y: 8 },
263
- { x: 25, y: 8 },
1067
+ { x: -90, y: 8 },
1068
+ { x: 90, y: 8 },
264
1069
  ],
265
1070
  },
266
1071
  {
@@ -270,8 +1075,8 @@ test("comprehensive soldermask margin test", async () => {
270
1075
  layer: "top",
271
1076
  stroke_width: 0.1,
272
1077
  route: [
273
- { x: -25, y: 0 },
274
- { x: 25, y: 0 },
1078
+ { x: -90, y: 0 },
1079
+ { x: 90, y: 0 },
275
1080
  ],
276
1081
  },
277
1082
  {
@@ -281,47 +1086,193 @@ test("comprehensive soldermask margin test", async () => {
281
1086
  layer: "top",
282
1087
  stroke_width: 0.1,
283
1088
  route: [
284
- { x: -25, y: -8 },
285
- { x: 25, y: -8 },
1089
+ { x: -90, y: -8 },
1090
+ { x: 90, y: -8 },
286
1091
  ],
287
1092
  },
288
- // Column labels
1093
+
1094
+ // =====================================================
1095
+ // Column labels (top)
1096
+ // =====================================================
1097
+ {
1098
+ type: "pcb_silkscreen_text",
1099
+ pcb_silkscreen_text_id: "label_col_rotated_rect",
1100
+ pcb_component_id: "dummy_component",
1101
+ text: "ROT RECT",
1102
+ layer: "top",
1103
+ anchor_position: { x: col.rotatedRect, y: 18 },
1104
+ anchor_alignment: "center",
1105
+ font_size: 0.8,
1106
+ font: "tscircuit2024",
1107
+ },
1108
+ {
1109
+ type: "pcb_silkscreen_text",
1110
+ pcb_silkscreen_text_id: "label_col_polygon",
1111
+ pcb_component_id: "dummy_component",
1112
+ text: "POLYGON",
1113
+ layer: "top",
1114
+ anchor_position: { x: col.polygon, y: 18 },
1115
+ anchor_alignment: "center",
1116
+ font_size: 0.8,
1117
+ font: "tscircuit2024",
1118
+ },
1119
+ {
1120
+ type: "pcb_silkscreen_text",
1121
+ pcb_silkscreen_text_id: "label_col_pill",
1122
+ pcb_component_id: "dummy_component",
1123
+ text: "PILL",
1124
+ layer: "top",
1125
+ anchor_position: { x: col.pill, y: 18 },
1126
+ anchor_alignment: "center",
1127
+ font_size: 0.8,
1128
+ font: "tscircuit2024",
1129
+ },
1130
+ {
1131
+ type: "pcb_silkscreen_text",
1132
+ pcb_silkscreen_text_id: "label_col_rotated_pill",
1133
+ pcb_component_id: "dummy_component",
1134
+ text: "ROT PILL",
1135
+ layer: "top",
1136
+ anchor_position: { x: col.rotatedPill, y: 18 },
1137
+ anchor_alignment: "center",
1138
+ font_size: 0.8,
1139
+ font: "tscircuit2024",
1140
+ },
1141
+ {
1142
+ type: "pcb_silkscreen_text",
1143
+ pcb_silkscreen_text_id: "label_col_circle_pad",
1144
+ pcb_component_id: "dummy_component",
1145
+ text: "CIRCLE",
1146
+ layer: "top",
1147
+ anchor_position: { x: col.circlePad, y: 18 },
1148
+ anchor_alignment: "center",
1149
+ font_size: 0.8,
1150
+ font: "tscircuit2024",
1151
+ },
1152
+ {
1153
+ type: "pcb_silkscreen_text",
1154
+ pcb_silkscreen_text_id: "label_col_rect_pad",
1155
+ pcb_component_id: "dummy_component",
1156
+ text: "RECT",
1157
+ layer: "top",
1158
+ anchor_position: { x: col.rectPad, y: 18 },
1159
+ anchor_alignment: "center",
1160
+ font_size: 0.8,
1161
+ font: "tscircuit2024",
1162
+ },
1163
+ {
1164
+ type: "pcb_silkscreen_text",
1165
+ pcb_silkscreen_text_id: "label_col_circle_plated",
1166
+ pcb_component_id: "dummy_component",
1167
+ text: "CIRC PTH",
1168
+ layer: "top",
1169
+ anchor_position: { x: col.circlePlatedHole, y: 18 },
1170
+ anchor_alignment: "center",
1171
+ font_size: 0.8,
1172
+ font: "tscircuit2024",
1173
+ },
1174
+ {
1175
+ type: "pcb_silkscreen_text",
1176
+ pcb_silkscreen_text_id: "label_col_oval_plated",
1177
+ pcb_component_id: "dummy_component",
1178
+ text: "OVAL PTH",
1179
+ layer: "top",
1180
+ anchor_position: { x: col.ovalPlatedHole, y: 18 },
1181
+ anchor_alignment: "center",
1182
+ font_size: 0.8,
1183
+ font: "tscircuit2024",
1184
+ },
1185
+ {
1186
+ type: "pcb_silkscreen_text",
1187
+ pcb_silkscreen_text_id: "label_col_pill_plated",
1188
+ pcb_component_id: "dummy_component",
1189
+ text: "PILL PTH",
1190
+ layer: "top",
1191
+ anchor_position: { x: col.pillPlatedHole, y: 18 },
1192
+ anchor_alignment: "center",
1193
+ font_size: 0.8,
1194
+ font: "tscircuit2024",
1195
+ },
1196
+ {
1197
+ type: "pcb_silkscreen_text",
1198
+ pcb_silkscreen_text_id: "label_col_circ_rect",
1199
+ pcb_component_id: "dummy_component",
1200
+ text: "C+RECT",
1201
+ layer: "top",
1202
+ anchor_position: { x: col.circRectPTH, y: 18 },
1203
+ anchor_alignment: "center",
1204
+ font_size: 0.8,
1205
+ font: "tscircuit2024",
1206
+ },
1207
+ {
1208
+ type: "pcb_silkscreen_text",
1209
+ pcb_silkscreen_text_id: "label_col_pill_rect",
1210
+ pcb_component_id: "dummy_component",
1211
+ text: "P+RECT",
1212
+ layer: "top",
1213
+ anchor_position: { x: col.pillRectPTH, y: 18 },
1214
+ anchor_alignment: "center",
1215
+ font_size: 0.8,
1216
+ font: "tscircuit2024",
1217
+ },
1218
+ {
1219
+ type: "pcb_silkscreen_text",
1220
+ pcb_silkscreen_text_id: "label_col_rot_pill_rect",
1221
+ pcb_component_id: "dummy_component",
1222
+ text: "RP+RECT",
1223
+ layer: "top",
1224
+ anchor_position: { x: col.rotPillRectPTH, y: 18 },
1225
+ anchor_alignment: "center",
1226
+ font_size: 0.8,
1227
+ font: "tscircuit2024",
1228
+ },
1229
+ {
1230
+ type: "pcb_silkscreen_text",
1231
+ pcb_silkscreen_text_id: "label_col_poly_pad",
1232
+ pcb_component_id: "dummy_component",
1233
+ text: "POLY PAD",
1234
+ layer: "top",
1235
+ anchor_position: { x: col.polyPadPTH, y: 18 },
1236
+ anchor_alignment: "center",
1237
+ font_size: 0.8,
1238
+ font: "tscircuit2024",
1239
+ },
289
1240
  {
290
1241
  type: "pcb_silkscreen_text",
291
- pcb_silkscreen_text_id: "label_pad",
1242
+ pcb_silkscreen_text_id: "label_col_circle_hole",
292
1243
  pcb_component_id: "dummy_component",
293
- text: "PADS",
1244
+ text: "CIRC HOLE",
294
1245
  layer: "top",
295
- anchor_position: { x: -15, y: 16 },
1246
+ anchor_position: { x: col.circleHole, y: 18 },
296
1247
  anchor_alignment: "center",
297
1248
  font_size: 0.8,
298
1249
  font: "tscircuit2024",
299
1250
  },
300
1251
  {
301
1252
  type: "pcb_silkscreen_text",
302
- pcb_silkscreen_text_id: "label_plated_hole",
1253
+ pcb_silkscreen_text_id: "label_col_oval_hole",
303
1254
  pcb_component_id: "dummy_component",
304
- text: "PLATED HOLE",
1255
+ text: "OVAL HOLE",
305
1256
  layer: "top",
306
- anchor_position: { x: -5, y: 16 },
1257
+ anchor_position: { x: col.ovalHole, y: 18 },
307
1258
  anchor_alignment: "center",
308
1259
  font_size: 0.8,
309
1260
  font: "tscircuit2024",
310
1261
  },
311
1262
  {
312
1263
  type: "pcb_silkscreen_text",
313
- pcb_silkscreen_text_id: "label_hole",
1264
+ pcb_silkscreen_text_id: "label_col_pill_hole",
314
1265
  pcb_component_id: "dummy_component",
315
- text: "HOLE",
1266
+ text: "PILL HOLE",
316
1267
  layer: "top",
317
- anchor_position: { x: 5, y: 16 },
1268
+ anchor_position: { x: col.pillHole, y: 18 },
318
1269
  anchor_alignment: "center",
319
1270
  font_size: 0.8,
320
1271
  font: "tscircuit2024",
321
1272
  },
322
1273
  ]
323
1274
 
324
- drawer.setCameraBounds({ minX: -30, maxX: 30, minY: -20, maxY: 20 })
1275
+ drawer.setCameraBounds({ minX: -95, maxX: 90, minY: -22, maxY: 22 })
325
1276
  drawer.drawElements(circuit)
326
1277
 
327
1278
  await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(