circuit-to-canvas 0.0.50 → 0.0.51

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 (51) hide show
  1. package/dist/index.d.ts +7 -4
  2. package/dist/index.js +1425 -1240
  3. package/lib/drawer/CircuitToCanvasDrawer.ts +262 -312
  4. package/lib/drawer/elements/helper-functions/draw-pill.ts +39 -0
  5. package/lib/drawer/elements/helper-functions/draw-polygon.ts +25 -0
  6. package/lib/drawer/elements/helper-functions/draw-rounded-rect.ts +34 -0
  7. package/lib/drawer/elements/helper-functions/index.ts +3 -0
  8. package/lib/drawer/elements/pcb-board.ts +13 -3
  9. package/lib/drawer/elements/pcb-hole.ts +56 -338
  10. package/lib/drawer/elements/pcb-plated-hole.ts +154 -442
  11. package/lib/drawer/elements/pcb-smtpad.ts +3 -292
  12. package/lib/drawer/elements/pcb-soldermask/board.ts +44 -0
  13. package/lib/drawer/elements/pcb-soldermask/cutout.ts +74 -0
  14. package/lib/drawer/elements/pcb-soldermask/hole.ts +288 -0
  15. package/lib/drawer/elements/pcb-soldermask/index.ts +140 -0
  16. package/lib/drawer/elements/pcb-soldermask/plated-hole.ts +365 -0
  17. package/lib/drawer/elements/pcb-soldermask/smt-pad.ts +354 -0
  18. package/lib/drawer/elements/pcb-soldermask/via.ts +27 -0
  19. package/package.json +1 -1
  20. package/tests/board-snapshot/__snapshots__/usb-c-flashlight-board.snap.png +0 -0
  21. package/tests/board-snapshot/usb-c-flashlight-board.test.ts +1 -0
  22. package/tests/elements/__snapshots__/board-with-elements.snap.png +0 -0
  23. package/tests/elements/__snapshots__/brep-copper-pours.snap.png +0 -0
  24. package/tests/elements/__snapshots__/custom-outline-board.snap.png +0 -0
  25. package/tests/elements/__snapshots__/oval-plated-hole.snap.png +0 -0
  26. package/tests/elements/__snapshots__/pcb-board.snap.png +0 -0
  27. package/tests/elements/__snapshots__/pcb-comprehensive-soldermask-margin.snap.png +0 -0
  28. package/tests/elements/__snapshots__/pcb-fabrication-note-dimension.snap.png +0 -0
  29. package/tests/elements/__snapshots__/pcb-hole-soldermask-margin.snap.png +0 -0
  30. package/tests/elements/__snapshots__/pcb-keepout-layer-filter.snap.png +0 -0
  31. package/tests/elements/__snapshots__/pcb-keepout-multiple-layers.snap.png +0 -0
  32. package/tests/elements/__snapshots__/pcb-keepout-rect-and-circle.snap.png +0 -0
  33. package/tests/elements/__snapshots__/pcb-keepout-with-group-id.snap.png +0 -0
  34. package/tests/elements/__snapshots__/pcb-no-soldermask.snap.png +0 -0
  35. package/tests/elements/__snapshots__/pcb-plated-hole-soldermask-margin.snap.png +0 -0
  36. package/tests/elements/__snapshots__/pcb-plated-hole.snap.png +0 -0
  37. package/tests/elements/__snapshots__/pcb-silkscreen-on-component.snap.png +0 -0
  38. package/tests/elements/__snapshots__/pcb-silkscreen-oval.snap.png +0 -0
  39. package/tests/elements/__snapshots__/pcb-smtpad-asymmetric-soldermask-margin.snap.png +0 -0
  40. package/tests/elements/__snapshots__/pcb-smtpad-soldermask-coverage.snap.png +0 -0
  41. package/tests/elements/__snapshots__/pcb-smtpad-soldermask-margin.snap.png +0 -0
  42. package/tests/elements/__snapshots__/pill-plated-hole.snap.png +0 -0
  43. package/tests/elements/pcb-comprehensive-soldermask-margin.test.ts +2 -2
  44. package/tests/elements/pcb-hole-soldermask-margin.test.ts +155 -2
  45. package/tests/elements/pcb-no-soldermask.test.ts +1281 -0
  46. package/tests/elements/pcb-plated-hole-soldermask-margin.test.ts +1 -1
  47. package/tests/elements/pcb-plated-hole.test.ts +40 -4
  48. package/tests/elements/pcb-smtpad-asymmetric-soldermask-margin.test.ts +1 -1
  49. package/tests/elements/pcb-smtpad-soldermask-coverage.test.ts +1 -1
  50. package/tests/elements/pcb-smtpad-soldermask-margin.test.ts +1 -1
  51. package/tests/fixtures/getStackedPngSvgComparison.ts +8 -2
@@ -0,0 +1,1281 @@
1
+ import { expect, test } from "bun:test"
2
+ import { createCanvas } from "@napi-rs/canvas"
3
+ import type { AnyCircuitElement } from "circuit-json"
4
+ import { CircuitToCanvasDrawer } from "../../lib/drawer"
5
+
6
+ /**
7
+ * Comprehensive test for soldermask margin functionality:
8
+ * - Row 1: Fully covered elements (is_covered_with_solder_mask = true)
9
+ * - Row 2: Positive margin (soldermask_margin = 0.5)
10
+ * - Row 3: Negative margin (soldermask_margin = -0.3)
11
+ * - Row 4: Default behavior (no margin specified)
12
+ *
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
33
+ */
34
+ test("comprehensive soldermask margin test", async () => {
35
+ const canvas = createCanvas(1800, 1000)
36
+ const ctx = canvas.getContext("2d")
37
+ const drawer = new CircuitToCanvasDrawer(ctx)
38
+
39
+ ctx.fillStyle = "#1a1a1a"
40
+ ctx.fillRect(0, 0, 2000, 1000)
41
+
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[] = [
90
+ {
91
+ type: "pcb_board",
92
+ pcb_board_id: "board_test",
93
+ center: { x: 0, y: 0 },
94
+ width: 180,
95
+ height: 45,
96
+ thickness: 1.6,
97
+ num_layers: 2,
98
+ material: "fr4",
99
+ },
100
+ // Dummy component for silkscreen elements
101
+ {
102
+ type: "pcb_component",
103
+ pcb_component_id: "dummy_component",
104
+ center: { x: 0, y: 0 },
105
+ width: 180,
106
+ height: 45,
107
+ rotation: 0,
108
+ layer: "top",
109
+ source_component_id: "dummy",
110
+ obstructs_within_bounds: false,
111
+ },
112
+
113
+ // =====================================================
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
174
+ {
175
+ type: "pcb_smtpad",
176
+ pcb_smtpad_id: "pad_fully_covered_circle",
177
+ shape: "circle",
178
+ x: col.circlePad,
179
+ y: row.fullyCovered,
180
+ radius: 1,
181
+ layer: "top",
182
+ is_covered_with_solder_mask: true,
183
+ },
184
+ // Column 6: Rect SMT Pad
185
+ {
186
+ type: "pcb_smtpad",
187
+ pcb_smtpad_id: "pad_fully_covered_rect",
188
+ shape: "rect",
189
+ x: col.rectPad,
190
+ y: row.fullyCovered,
191
+ width: 2,
192
+ height: 2,
193
+ layer: "top",
194
+ is_covered_with_solder_mask: true,
195
+ },
196
+ // Column 7: Circle Plated Hole
197
+ {
198
+ type: "pcb_plated_hole",
199
+ pcb_plated_hole_id: "hole_fully_covered_circle",
200
+ shape: "circle",
201
+ x: col.circlePlatedHole,
202
+ y: row.fullyCovered,
203
+ hole_diameter: 1,
204
+ outer_diameter: 2,
205
+ layers: ["top", "bottom"],
206
+ is_covered_with_solder_mask: true,
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
309
+ {
310
+ type: "pcb_hole",
311
+ pcb_hole_id: "np_hole_fully_covered_circle",
312
+ hole_shape: "circle",
313
+ x: col.circleHole,
314
+ y: row.fullyCovered,
315
+ hole_diameter: 1,
316
+ is_covered_with_solder_mask: true,
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
+ // =====================================================
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
402
+ {
403
+ type: "pcb_smtpad",
404
+ pcb_smtpad_id: "pad_positive_margin_circle",
405
+ shape: "circle",
406
+ x: col.circlePad,
407
+ y: row.positiveMargin,
408
+ radius: 1,
409
+ layer: "top",
410
+ soldermask_margin: 0.5,
411
+ },
412
+ // Column 6: Rect SMT Pad
413
+ {
414
+ type: "pcb_smtpad",
415
+ pcb_smtpad_id: "pad_positive_margin_rect",
416
+ shape: "rect",
417
+ x: col.rectPad,
418
+ y: row.positiveMargin,
419
+ width: 2,
420
+ height: 2,
421
+ layer: "top",
422
+ soldermask_margin: 0.5,
423
+ },
424
+ // Column 7: Circle Plated Hole
425
+ {
426
+ type: "pcb_plated_hole",
427
+ pcb_plated_hole_id: "hole_positive_margin_circle",
428
+ shape: "circle",
429
+ x: col.circlePlatedHole,
430
+ y: row.positiveMargin,
431
+ hole_diameter: 1,
432
+ outer_diameter: 2,
433
+ layers: ["top", "bottom"],
434
+ soldermask_margin: 0.5,
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
537
+ {
538
+ type: "pcb_hole",
539
+ pcb_hole_id: "np_hole_positive_margin_circle",
540
+ hole_shape: "circle",
541
+ x: col.circleHole,
542
+ y: row.positiveMargin,
543
+ hole_diameter: 1,
544
+ soldermask_margin: 0.5,
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
+ // =====================================================
570
+ // Row 3: Negative margin (soldermask_margin = -0.3)
571
+ // =====================================================
572
+
573
+ // Column 1: Rotated Rect SMT Pad
574
+ {
575
+ type: "pcb_smtpad",
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",
633
+ shape: "circle",
634
+ x: col.circlePad,
635
+ y: row.negativeMargin,
636
+ radius: 1,
637
+ layer: "top",
638
+ soldermask_margin: -0.3,
639
+ },
640
+ // Column 6: Rect SMT Pad
641
+ {
642
+ type: "pcb_smtpad",
643
+ pcb_smtpad_id: "pad_negative_margin_rect",
644
+ shape: "rect",
645
+ x: col.rectPad,
646
+ y: row.negativeMargin,
647
+ width: 2,
648
+ height: 2,
649
+ layer: "top",
650
+ soldermask_margin: -0.3,
651
+ },
652
+ // Column 7: Circle Plated Hole
653
+ {
654
+ type: "pcb_plated_hole",
655
+ pcb_plated_hole_id: "hole_negative_margin_circle",
656
+ shape: "circle",
657
+ x: col.circlePlatedHole,
658
+ y: row.negativeMargin,
659
+ hole_diameter: 1,
660
+ outer_diameter: 2,
661
+ layers: ["top", "bottom"],
662
+ soldermask_margin: -0.3,
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
765
+ {
766
+ type: "pcb_hole",
767
+ pcb_hole_id: "np_hole_negative_margin_circle",
768
+ hole_shape: "circle",
769
+ x: col.circleHole,
770
+ y: row.negativeMargin,
771
+ hole_diameter: 1,
772
+ soldermask_margin: -0.3,
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
+ // =====================================================
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
841
+ {
842
+ type: "pcb_smtpad",
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",
857
+ shape: "circle",
858
+ x: col.circlePad,
859
+ y: row.default,
860
+ radius: 1,
861
+ layer: "top",
862
+ },
863
+ // Column 6: Rect SMT Pad
864
+ {
865
+ type: "pcb_smtpad",
866
+ pcb_smtpad_id: "pad_default_rect",
867
+ shape: "rect",
868
+ x: col.rectPad,
869
+ y: row.default,
870
+ width: 2,
871
+ height: 2,
872
+ layer: "top",
873
+ },
874
+ // Column 7: Circle Plated Hole
875
+ {
876
+ type: "pcb_plated_hole",
877
+ pcb_plated_hole_id: "hole_default_circle",
878
+ shape: "circle",
879
+ x: col.circlePlatedHole,
880
+ y: row.default,
881
+ hole_diameter: 1,
882
+ outer_diameter: 2,
883
+ layers: ["top", "bottom"],
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
980
+ {
981
+ type: "pcb_hole",
982
+ pcb_hole_id: "np_hole_default_circle",
983
+ hole_shape: "circle",
984
+ x: col.circleHole,
985
+ y: row.default,
986
+ hole_diameter: 1,
987
+ },
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
+ // =====================================================
1012
+ {
1013
+ type: "pcb_silkscreen_text",
1014
+ pcb_silkscreen_text_id: "label_fully_covered",
1015
+ pcb_component_id: "dummy_component",
1016
+ text: "FULLY COVERED",
1017
+ layer: "top",
1018
+ anchor_position: { x: -90, y: row.fullyCovered },
1019
+ anchor_alignment: "center_left",
1020
+ font_size: 1,
1021
+ font: "tscircuit2024",
1022
+ },
1023
+ {
1024
+ type: "pcb_silkscreen_text",
1025
+ pcb_silkscreen_text_id: "label_positive_margin",
1026
+ pcb_component_id: "dummy_component",
1027
+ text: "POSITIVE MARGIN",
1028
+ layer: "top",
1029
+ anchor_position: { x: -90, y: row.positiveMargin },
1030
+ anchor_alignment: "center_left",
1031
+ font_size: 1,
1032
+ font: "tscircuit2024",
1033
+ },
1034
+ {
1035
+ type: "pcb_silkscreen_text",
1036
+ pcb_silkscreen_text_id: "label_negative_margin",
1037
+ pcb_component_id: "dummy_component",
1038
+ text: "NEGATIVE MARGIN",
1039
+ layer: "top",
1040
+ anchor_position: { x: -90, y: row.negativeMargin },
1041
+ anchor_alignment: "center_left",
1042
+ font_size: 1,
1043
+ font: "tscircuit2024",
1044
+ },
1045
+ {
1046
+ type: "pcb_silkscreen_text",
1047
+ pcb_silkscreen_text_id: "label_default",
1048
+ pcb_component_id: "dummy_component",
1049
+ text: "DEFAULT",
1050
+ layer: "top",
1051
+ anchor_position: { x: -90, y: row.default },
1052
+ anchor_alignment: "center_left",
1053
+ font_size: 1,
1054
+ font: "tscircuit2024",
1055
+ },
1056
+
1057
+ // =====================================================
1058
+ // Row separators
1059
+ // =====================================================
1060
+ {
1061
+ type: "pcb_silkscreen_path",
1062
+ pcb_silkscreen_path_id: "separator_1",
1063
+ pcb_component_id: "dummy_component",
1064
+ layer: "top",
1065
+ stroke_width: 0.1,
1066
+ route: [
1067
+ { x: -90, y: 8 },
1068
+ { x: 90, y: 8 },
1069
+ ],
1070
+ },
1071
+ {
1072
+ type: "pcb_silkscreen_path",
1073
+ pcb_silkscreen_path_id: "separator_2",
1074
+ pcb_component_id: "dummy_component",
1075
+ layer: "top",
1076
+ stroke_width: 0.1,
1077
+ route: [
1078
+ { x: -90, y: 0 },
1079
+ { x: 90, y: 0 },
1080
+ ],
1081
+ },
1082
+ {
1083
+ type: "pcb_silkscreen_path",
1084
+ pcb_silkscreen_path_id: "separator_3",
1085
+ pcb_component_id: "dummy_component",
1086
+ layer: "top",
1087
+ stroke_width: 0.1,
1088
+ route: [
1089
+ { x: -90, y: -8 },
1090
+ { x: 90, y: -8 },
1091
+ ],
1092
+ },
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
+ },
1240
+ {
1241
+ type: "pcb_silkscreen_text",
1242
+ pcb_silkscreen_text_id: "label_col_circle_hole",
1243
+ pcb_component_id: "dummy_component",
1244
+ text: "CIRC HOLE",
1245
+ layer: "top",
1246
+ anchor_position: { x: col.circleHole, y: 18 },
1247
+ anchor_alignment: "center",
1248
+ font_size: 0.8,
1249
+ font: "tscircuit2024",
1250
+ },
1251
+ {
1252
+ type: "pcb_silkscreen_text",
1253
+ pcb_silkscreen_text_id: "label_col_oval_hole",
1254
+ pcb_component_id: "dummy_component",
1255
+ text: "OVAL HOLE",
1256
+ layer: "top",
1257
+ anchor_position: { x: col.ovalHole, y: 18 },
1258
+ anchor_alignment: "center",
1259
+ font_size: 0.8,
1260
+ font: "tscircuit2024",
1261
+ },
1262
+ {
1263
+ type: "pcb_silkscreen_text",
1264
+ pcb_silkscreen_text_id: "label_col_pill_hole",
1265
+ pcb_component_id: "dummy_component",
1266
+ text: "PILL HOLE",
1267
+ layer: "top",
1268
+ anchor_position: { x: col.pillHole, y: 18 },
1269
+ anchor_alignment: "center",
1270
+ font_size: 0.8,
1271
+ font: "tscircuit2024",
1272
+ },
1273
+ ]
1274
+
1275
+ drawer.setCameraBounds({ minX: -95, maxX: 90, minY: -22, maxY: 22 })
1276
+ drawer.drawElements(circuit)
1277
+
1278
+ await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
1279
+ import.meta.path,
1280
+ )
1281
+ })