circuit-json-to-lbrn 0.0.40 → 0.0.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ interface ConvertCircuitJsonToLbrnOptions {
11
11
  includeCopper?: boolean;
12
12
  includeSoldermask?: boolean;
13
13
  globalCopperSoldermaskMarginAdjustment?: number;
14
+ solderMaskMarginPercent?: number;
14
15
  includeLayers?: Array<"top" | "bottom">;
15
16
  traceMargin?: number;
16
17
  laserSpotSize?: number;
package/dist/index.js CHANGED
@@ -62,6 +62,7 @@ var addCirclePlatedHole = (platedHole, ctx) => {
62
62
  includeSoldermask,
63
63
  connMap,
64
64
  globalCopperSoldermaskMarginAdjustment,
65
+ solderMaskMarginPercent,
65
66
  includeLayers
66
67
  } = ctx;
67
68
  const centerX = platedHole.x + origin.x;
@@ -107,7 +108,9 @@ var addCirclePlatedHole = (platedHole, ctx) => {
107
108
  }
108
109
  }
109
110
  if (platedHole.outer_diameter > 0 && includeSoldermask) {
110
- const smRadius = platedHole.outer_diameter / 2 + globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0);
111
+ const percentMargin = solderMaskMarginPercent / 100 * platedHole.outer_diameter;
112
+ const totalMargin = globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0) + percentMargin;
113
+ const smRadius = Math.max(platedHole.outer_diameter / 2 + totalMargin, 0);
111
114
  const outer = createCirclePath({
112
115
  centerX,
113
116
  centerY,
@@ -189,6 +192,7 @@ var addOvalPlatedHole = (platedHole, ctx) => {
189
192
  includeCopper,
190
193
  includeSoldermask,
191
194
  globalCopperSoldermaskMarginAdjustment,
195
+ solderMaskMarginPercent,
192
196
  includeLayers
193
197
  } = ctx;
194
198
  if (platedHole.outer_width <= 0 || platedHole.outer_height <= 0) {
@@ -227,9 +231,18 @@ var addOvalPlatedHole = (platedHole, ctx) => {
227
231
  }
228
232
  }
229
233
  if (platedHole.outer_width > 0 && platedHole.outer_height > 0 && includeSoldermask) {
230
- const soldermaskMargin = globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0);
231
- const smWidth = platedHole.outer_width + 2 * soldermaskMargin;
232
- const smHeight = platedHole.outer_height + 2 * soldermaskMargin;
234
+ const percentMarginX = solderMaskMarginPercent / 100 * platedHole.outer_width;
235
+ const percentMarginY = solderMaskMarginPercent / 100 * platedHole.outer_height;
236
+ const totalMarginX = Math.max(
237
+ globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0) + percentMarginX,
238
+ -platedHole.outer_width / 2
239
+ );
240
+ const totalMarginY = Math.max(
241
+ globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0) + percentMarginY,
242
+ -platedHole.outer_height / 2
243
+ );
244
+ const smWidth = platedHole.outer_width + 2 * totalMarginX;
245
+ const smHeight = platedHole.outer_height + 2 * totalMarginY;
233
246
  const outer = createOvalPath({
234
247
  centerX,
235
248
  centerY,
@@ -412,6 +425,7 @@ var addCircularHoleWithRectPad = (platedHole, ctx) => {
412
425
  includeCopper,
413
426
  includeSoldermask,
414
427
  globalCopperSoldermaskMarginAdjustment,
428
+ solderMaskMarginPercent,
415
429
  includeLayers
416
430
  } = ctx;
417
431
  const centerX = platedHole.x + origin.x;
@@ -442,8 +456,18 @@ var addCircularHoleWithRectPad = (platedHole, ctx) => {
442
456
  });
443
457
  }
444
458
  if (includeSoldermask) {
445
- const smPadWidth = padWidth + 2 * globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0);
446
- const smPadHeight = padHeight + 2 * globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0);
459
+ const percentMarginX = solderMaskMarginPercent / 100 * padWidth;
460
+ const percentMarginY = solderMaskMarginPercent / 100 * padHeight;
461
+ const totalMarginX = Math.max(
462
+ globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0) + percentMarginX,
463
+ -padWidth / 2
464
+ );
465
+ const totalMarginY = Math.max(
466
+ globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0) + percentMarginY,
467
+ -padHeight / 2
468
+ );
469
+ const smPadWidth = padWidth + 2 * totalMarginX;
470
+ const smPadHeight = padHeight + 2 * totalMarginY;
447
471
  const smPadPath = createRoundedRectPath({
448
472
  centerX,
449
473
  centerY,
@@ -587,6 +611,7 @@ var addPillHoleWithRectPad = (platedHole, ctx) => {
587
611
  includeCopper,
588
612
  includeSoldermask,
589
613
  globalCopperSoldermaskMarginAdjustment,
614
+ solderMaskMarginPercent,
590
615
  includeLayers
591
616
  } = ctx;
592
617
  const centerX = platedHole.x + origin.x;
@@ -617,8 +642,18 @@ var addPillHoleWithRectPad = (platedHole, ctx) => {
617
642
  });
618
643
  }
619
644
  if (includeSoldermask) {
620
- const smPadWidth = padWidth + 2 * globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0);
621
- const smPadHeight = padHeight + 2 * globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0);
645
+ const percentMarginX = solderMaskMarginPercent / 100 * padWidth;
646
+ const percentMarginY = solderMaskMarginPercent / 100 * padHeight;
647
+ const totalMarginX = Math.max(
648
+ globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0) + percentMarginX,
649
+ -padWidth / 2
650
+ );
651
+ const totalMarginY = Math.max(
652
+ globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0) + percentMarginY,
653
+ -padHeight / 2
654
+ );
655
+ const smPadWidth = padWidth + 2 * totalMarginX;
656
+ const smPadHeight = padHeight + 2 * totalMarginY;
622
657
  const smPadPath = createRoundedRectPath({
623
658
  centerX,
624
659
  centerY,
@@ -669,6 +704,7 @@ var addRotatedPillHoleWithRectPad = (platedHole, ctx) => {
669
704
  includeCopper,
670
705
  includeSoldermask,
671
706
  globalCopperSoldermaskMarginAdjustment,
707
+ solderMaskMarginPercent,
672
708
  includeLayers
673
709
  } = ctx;
674
710
  const centerX = platedHole.x + origin.x;
@@ -702,8 +738,18 @@ var addRotatedPillHoleWithRectPad = (platedHole, ctx) => {
702
738
  });
703
739
  }
704
740
  if (includeSoldermask) {
705
- const smPadWidth = padWidth + 2 * globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0);
706
- const smPadHeight = padHeight + 2 * globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0);
741
+ const percentMarginX = solderMaskMarginPercent / 100 * padWidth;
742
+ const percentMarginY = solderMaskMarginPercent / 100 * padHeight;
743
+ const totalMarginX = Math.max(
744
+ globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0) + percentMarginX,
745
+ -padWidth / 2
746
+ );
747
+ const totalMarginY = Math.max(
748
+ globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0) + percentMarginY,
749
+ -padHeight / 2
750
+ );
751
+ const smPadWidth = padWidth + 2 * totalMarginX;
752
+ const smPadHeight = padHeight + 2 * totalMarginY;
707
753
  const smPadPath = createRoundedRectPath({
708
754
  centerX,
709
755
  centerY,
@@ -867,6 +913,7 @@ var addPcbPlatedHolePill = (platedHole, ctx) => {
867
913
  includeCopper,
868
914
  includeSoldermask,
869
915
  globalCopperSoldermaskMarginAdjustment,
916
+ solderMaskMarginPercent,
870
917
  includeLayers
871
918
  } = ctx;
872
919
  const centerX = platedHole.x + origin.x;
@@ -902,8 +949,18 @@ var addPcbPlatedHolePill = (platedHole, ctx) => {
902
949
  }
903
950
  }
904
951
  if (platedHole.outer_width > 0 && platedHole.outer_height > 0 && includeSoldermask) {
905
- const smWidth = platedHole.outer_width + 2 * globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0);
906
- const smHeight = platedHole.outer_height + 2 * globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0);
952
+ const percentMarginX = solderMaskMarginPercent / 100 * platedHole.outer_width;
953
+ const percentMarginY = solderMaskMarginPercent / 100 * platedHole.outer_height;
954
+ const totalMarginX = Math.max(
955
+ globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0) + percentMarginX,
956
+ -platedHole.outer_width / 2
957
+ );
958
+ const totalMarginY = Math.max(
959
+ globalCopperSoldermaskMarginAdjustment + (platedHole.soldermask_margin ?? 0) + percentMarginY,
960
+ -platedHole.outer_height / 2
961
+ );
962
+ const smWidth = platedHole.outer_width + 2 * totalMarginX;
963
+ const smHeight = platedHole.outer_height + 2 * totalMarginY;
907
964
  const outer = createPillPath({
908
965
  centerX,
909
966
  centerY,
@@ -973,6 +1030,7 @@ var addRectSmtPad = (smtPad, ctx) => {
973
1030
  includeCopper,
974
1031
  includeSoldermask,
975
1032
  globalCopperSoldermaskMarginAdjustment,
1033
+ solderMaskMarginPercent,
976
1034
  includeLayers
977
1035
  } = ctx;
978
1036
  const padLayer = smtPad.layer || "top";
@@ -1006,8 +1064,18 @@ var addRectSmtPad = (smtPad, ctx) => {
1006
1064
  });
1007
1065
  }
1008
1066
  if (includeSoldermask) {
1009
- const smHalfWidth = halfWidth + globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0);
1010
- const smHalfHeight = halfHeight + globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0);
1067
+ const percentMarginX = solderMaskMarginPercent / 100 * smtPad.width;
1068
+ const percentMarginY = solderMaskMarginPercent / 100 * smtPad.height;
1069
+ const totalMarginX = Math.max(
1070
+ globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0) + percentMarginX,
1071
+ -smtPad.width / 2
1072
+ );
1073
+ const totalMarginY = Math.max(
1074
+ globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0) + percentMarginY,
1075
+ -smtPad.height / 2
1076
+ );
1077
+ const smHalfWidth = halfWidth + totalMarginX;
1078
+ const smHalfHeight = halfHeight + totalMarginY;
1011
1079
  const verts = [
1012
1080
  { x: centerX - smHalfWidth, y: centerY - smHalfHeight },
1013
1081
  { x: centerX + smHalfWidth, y: centerY - smHalfHeight },
@@ -1044,6 +1112,7 @@ var addCircleSmtPad = (smtPad, ctx) => {
1044
1112
  includeCopper,
1045
1113
  includeSoldermask,
1046
1114
  globalCopperSoldermaskMarginAdjustment,
1115
+ solderMaskMarginPercent,
1047
1116
  includeLayers
1048
1117
  } = ctx;
1049
1118
  const padLayer = smtPad.layer || "top";
@@ -1071,7 +1140,19 @@ var addCircleSmtPad = (smtPad, ctx) => {
1071
1140
  });
1072
1141
  }
1073
1142
  if (includeSoldermask) {
1074
- const smRadius = outerRadius + globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0);
1143
+ const elementWidth = 2 * outerRadius;
1144
+ const elementHeight = 2 * outerRadius;
1145
+ const percentMarginX = solderMaskMarginPercent / 100 * elementWidth;
1146
+ const percentMarginY = solderMaskMarginPercent / 100 * elementHeight;
1147
+ const totalMarginX = Math.max(
1148
+ globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0) + percentMarginX,
1149
+ -elementWidth / 2
1150
+ );
1151
+ const totalMarginY = Math.max(
1152
+ globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0) + percentMarginY,
1153
+ -elementHeight / 2
1154
+ );
1155
+ const smRadius = outerRadius + totalMarginX;
1075
1156
  const outer = createCirclePath({
1076
1157
  centerX,
1077
1158
  centerY,
@@ -1099,6 +1180,7 @@ var addPillSmtPad = (smtPad, ctx) => {
1099
1180
  includeCopper,
1100
1181
  includeSoldermask,
1101
1182
  globalCopperSoldermaskMarginAdjustment,
1183
+ solderMaskMarginPercent,
1102
1184
  includeLayers
1103
1185
  } = ctx;
1104
1186
  const padLayer = smtPad.layer || "top";
@@ -1126,8 +1208,18 @@ var addPillSmtPad = (smtPad, ctx) => {
1126
1208
  });
1127
1209
  }
1128
1210
  if (includeSoldermask) {
1129
- const smWidth = smtPad.width + 2 * globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0);
1130
- const smHeight = smtPad.height + 2 * globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0);
1211
+ const percentMarginX = solderMaskMarginPercent / 100 * smtPad.width;
1212
+ const percentMarginY = solderMaskMarginPercent / 100 * smtPad.height;
1213
+ const totalMarginX = Math.max(
1214
+ globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0) + percentMarginX,
1215
+ -smtPad.width / 2
1216
+ );
1217
+ const totalMarginY = Math.max(
1218
+ globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0) + percentMarginY,
1219
+ -smtPad.height / 2
1220
+ );
1221
+ const smWidth = smtPad.width + 2 * totalMarginX;
1222
+ const smHeight = smtPad.height + 2 * totalMarginY;
1131
1223
  const smOuter = createPillPath({
1132
1224
  centerX,
1133
1225
  centerY,
@@ -1156,6 +1248,7 @@ var addRotatedPillSmtPad = (smtPad, ctx) => {
1156
1248
  includeCopper,
1157
1249
  includeSoldermask,
1158
1250
  globalCopperSoldermaskMarginAdjustment,
1251
+ solderMaskMarginPercent,
1159
1252
  includeLayers
1160
1253
  } = ctx;
1161
1254
  const padLayer = smtPad.layer || "top";
@@ -1184,8 +1277,18 @@ var addRotatedPillSmtPad = (smtPad, ctx) => {
1184
1277
  });
1185
1278
  }
1186
1279
  if (includeSoldermask) {
1187
- const smWidth = smtPad.width + 2 * globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0);
1188
- const smHeight = smtPad.height + 2 * globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0);
1280
+ const percentMarginX = solderMaskMarginPercent / 100 * smtPad.width;
1281
+ const percentMarginY = solderMaskMarginPercent / 100 * smtPad.height;
1282
+ const totalMarginX = Math.max(
1283
+ globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0) + percentMarginX,
1284
+ -smtPad.width / 2
1285
+ );
1286
+ const totalMarginY = Math.max(
1287
+ globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0) + percentMarginY,
1288
+ -smtPad.height / 2
1289
+ );
1290
+ const smWidth = smtPad.width + 2 * totalMarginX;
1291
+ const smHeight = smtPad.height + 2 * totalMarginY;
1189
1292
  const smOuter = createPillPath({
1190
1293
  centerX,
1191
1294
  centerY,
@@ -1244,6 +1347,7 @@ var addPolygonSmtPad = (smtPad, ctx) => {
1244
1347
  includeCopper,
1245
1348
  includeSoldermask,
1246
1349
  globalCopperSoldermaskMarginAdjustment,
1350
+ solderMaskMarginPercent,
1247
1351
  includeLayers
1248
1352
  } = ctx;
1249
1353
  const padLayer = smtPad.layer || "top";
@@ -1290,6 +1394,7 @@ var addRotatedRectSmtPad = (smtPad, ctx) => {
1290
1394
  includeCopper,
1291
1395
  includeSoldermask,
1292
1396
  globalCopperSoldermaskMarginAdjustment,
1397
+ solderMaskMarginPercent,
1293
1398
  includeLayers
1294
1399
  } = ctx;
1295
1400
  const padLayer = smtPad.layer || "top";
@@ -1322,8 +1427,18 @@ var addRotatedRectSmtPad = (smtPad, ctx) => {
1322
1427
  });
1323
1428
  }
1324
1429
  if (includeSoldermask) {
1325
- const smWidth = smtPad.width + 2 * globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0);
1326
- const smHeight = smtPad.height + 2 * globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0);
1430
+ const percentMarginX = solderMaskMarginPercent / 100 * smtPad.width;
1431
+ const percentMarginY = solderMaskMarginPercent / 100 * smtPad.height;
1432
+ const totalMarginX = Math.max(
1433
+ globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0) + percentMarginX,
1434
+ -smtPad.width / 2
1435
+ );
1436
+ const totalMarginY = Math.max(
1437
+ globalCopperSoldermaskMarginAdjustment + (smtPad.soldermask_margin ?? 0) + percentMarginY,
1438
+ -smtPad.height / 2
1439
+ );
1440
+ const smWidth = smtPad.width + 2 * totalMarginX;
1441
+ const smHeight = smtPad.height + 2 * totalMarginY;
1327
1442
  const smOuter = createRoundedRectPath({
1328
1443
  centerX,
1329
1444
  centerY,
@@ -1833,6 +1948,7 @@ var addPcbVia = (via, ctx) => {
1833
1948
  includeSoldermask,
1834
1949
  connMap,
1835
1950
  globalCopperSoldermaskMarginAdjustment,
1951
+ solderMaskMarginPercent,
1836
1952
  includeLayers
1837
1953
  } = ctx;
1838
1954
  const centerX = via.x + origin.x;
@@ -1887,7 +2003,9 @@ var addPcbVia = (via, ctx) => {
1887
2003
  }
1888
2004
  }
1889
2005
  if (via.outer_diameter > 0 && includeSoldermask) {
1890
- const smRadius = via.outer_diameter / 2 + globalCopperSoldermaskMarginAdjustment;
2006
+ const percentMargin = solderMaskMarginPercent / 100 * via.outer_diameter;
2007
+ const totalMargin = globalCopperSoldermaskMarginAdjustment + percentMargin;
2008
+ const smRadius = Math.max(via.outer_diameter / 2 + totalMargin, 0);
1891
2009
  const outer = createCirclePath({
1892
2010
  centerX,
1893
2011
  centerY,
@@ -2376,6 +2494,7 @@ var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
2376
2494
  const includeCopper = options.includeCopper ?? true;
2377
2495
  const includeSoldermask = options.includeSoldermask ?? false;
2378
2496
  const globalCopperSoldermaskMarginAdjustment = options.globalCopperSoldermaskMarginAdjustment ?? 0;
2497
+ const solderMaskMarginPercent = options.solderMaskMarginPercent ?? 0;
2379
2498
  const laserProfile = options.laserProfile;
2380
2499
  const defaultCopperSettings = {
2381
2500
  speed: 300,
@@ -2492,7 +2611,8 @@ var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
2492
2611
  traceMargin,
2493
2612
  laserSpotSize,
2494
2613
  topTraceClearanceAreaCutSetting,
2495
- bottomTraceClearanceAreaCutSetting
2614
+ bottomTraceClearanceAreaCutSetting,
2615
+ solderMaskMarginPercent
2496
2616
  };
2497
2617
  for (const net of Object.keys(connMap.netMap)) {
2498
2618
  ctx.topCutNetGeoms.set(net, []);
@@ -43,4 +43,7 @@ export interface ConvertContext {
43
43
  // Cut settings for trace clearance areas
44
44
  topTraceClearanceAreaCutSetting?: CutSetting
45
45
  bottomTraceClearanceAreaCutSetting?: CutSetting
46
+
47
+ // Percent-based solder mask margin (scales with element size)
48
+ solderMaskMarginPercent: number
46
49
  }
@@ -20,6 +20,7 @@ export const addPcbVia = (via: PcbVia, ctx: ConvertContext): void => {
20
20
  includeSoldermask,
21
21
  connMap,
22
22
  globalCopperSoldermaskMarginAdjustment,
23
+ solderMaskMarginPercent,
23
24
  includeLayers,
24
25
  } = ctx
25
26
  const centerX = via.x + origin.x
@@ -93,8 +94,16 @@ export const addPcbVia = (via: PcbVia, ctx: ConvertContext): void => {
93
94
 
94
95
  // Add soldermask opening if drawing soldermask
95
96
  if (via.outer_diameter > 0 && includeSoldermask) {
96
- const smRadius =
97
- via.outer_diameter / 2 + globalCopperSoldermaskMarginAdjustment
97
+ // Percent margin is additive and may be negative.
98
+ // Global adjustment is always applied.
99
+ // Percent margin is applied to full diameter
100
+ const percentMargin = (solderMaskMarginPercent / 100) * via.outer_diameter
101
+
102
+ // Total margin is additive
103
+ const totalMargin = globalCopperSoldermaskMarginAdjustment + percentMargin
104
+
105
+ // Clamp so radius never goes below zero
106
+ const smRadius = Math.max(via.outer_diameter / 2 + totalMargin, 0)
98
107
  const outer = createCirclePath({
99
108
  centerX,
100
109
  centerY,
@@ -22,6 +22,7 @@ export const addCirclePlatedHole = (
22
22
  includeSoldermask,
23
23
  connMap,
24
24
  globalCopperSoldermaskMarginAdjustment,
25
+ solderMaskMarginPercent,
25
26
  includeLayers,
26
27
  } = ctx
27
28
  const centerX = platedHole.x + origin.x
@@ -75,10 +76,15 @@ export const addCirclePlatedHole = (
75
76
 
76
77
  // Add soldermask opening if drawing soldermask
77
78
  if (platedHole.outer_diameter > 0 && includeSoldermask) {
78
- const smRadius =
79
- platedHole.outer_diameter / 2 +
79
+ // Percent margin is additive and may be negative.
80
+ // Absolute per-element margin and global adjustment are always applied.
81
+ const percentMargin =
82
+ (solderMaskMarginPercent / 100) * platedHole.outer_diameter
83
+ const totalMargin =
80
84
  globalCopperSoldermaskMarginAdjustment +
81
- (platedHole.soldermask_margin ?? 0)
85
+ (platedHole.soldermask_margin ?? 0) +
86
+ percentMargin
87
+ const smRadius = Math.max(platedHole.outer_diameter / 2 + totalMargin, 0)
82
88
  const outer = createCirclePath({
83
89
  centerX,
84
90
  centerY,
@@ -17,6 +17,7 @@ export const addCircularHoleWithRectPad = (
17
17
  includeCopper,
18
18
  includeSoldermask,
19
19
  globalCopperSoldermaskMarginAdjustment,
20
+ solderMaskMarginPercent,
20
21
  includeLayers,
21
22
  } = ctx
22
23
  const centerX = platedHole.x + origin.x
@@ -54,14 +55,25 @@ export const addCircularHoleWithRectPad = (
54
55
 
55
56
  // Add soldermask opening if drawing soldermask
56
57
  if (includeSoldermask) {
57
- const smPadWidth =
58
- padWidth +
59
- 2 * globalCopperSoldermaskMarginAdjustment +
60
- (platedHole.soldermask_margin ?? 0)
61
- const smPadHeight =
62
- padHeight +
63
- 2 * globalCopperSoldermaskMarginAdjustment +
64
- (platedHole.soldermask_margin ?? 0)
58
+ // Percent margin is additive and may be negative.
59
+ // Absolute per-element margin and global adjustment are always applied.
60
+ const percentMarginX = (solderMaskMarginPercent / 100) * padWidth
61
+ const percentMarginY = (solderMaskMarginPercent / 100) * padHeight
62
+
63
+ const totalMarginX = Math.max(
64
+ globalCopperSoldermaskMarginAdjustment +
65
+ (platedHole.soldermask_margin ?? 0) +
66
+ percentMarginX,
67
+ -padWidth / 2,
68
+ )
69
+ const totalMarginY = Math.max(
70
+ globalCopperSoldermaskMarginAdjustment +
71
+ (platedHole.soldermask_margin ?? 0) +
72
+ percentMarginY,
73
+ -padHeight / 2,
74
+ )
75
+ const smPadWidth = padWidth + 2 * totalMarginX
76
+ const smPadHeight = padHeight + 2 * totalMarginY
65
77
  const smPadPath = createRoundedRectPath({
66
78
  centerX,
67
79
  centerY,
@@ -17,6 +17,7 @@ export const addOvalPlatedHole = (
17
17
  includeCopper,
18
18
  includeSoldermask,
19
19
  globalCopperSoldermaskMarginAdjustment,
20
+ solderMaskMarginPercent,
20
21
  includeLayers,
21
22
  } = ctx
22
23
 
@@ -70,11 +71,26 @@ export const addOvalPlatedHole = (
70
71
  platedHole.outer_height > 0 &&
71
72
  includeSoldermask
72
73
  ) {
73
- const soldermaskMargin =
74
+ // Percent margin is additive and may be negative.
75
+ // Absolute per-element margin and global adjustment are always applied.
76
+ const percentMarginX =
77
+ (solderMaskMarginPercent / 100) * platedHole.outer_width
78
+ const percentMarginY =
79
+ (solderMaskMarginPercent / 100) * platedHole.outer_height
80
+ const totalMarginX = Math.max(
74
81
  globalCopperSoldermaskMarginAdjustment +
75
- (platedHole.soldermask_margin ?? 0)
76
- const smWidth = platedHole.outer_width + 2 * soldermaskMargin
77
- const smHeight = platedHole.outer_height + 2 * soldermaskMargin
82
+ (platedHole.soldermask_margin ?? 0) +
83
+ percentMarginX,
84
+ -platedHole.outer_width / 2,
85
+ )
86
+ const totalMarginY = Math.max(
87
+ globalCopperSoldermaskMarginAdjustment +
88
+ (platedHole.soldermask_margin ?? 0) +
89
+ percentMarginY,
90
+ -platedHole.outer_height / 2,
91
+ )
92
+ const smWidth = platedHole.outer_width + 2 * totalMarginX
93
+ const smHeight = platedHole.outer_height + 2 * totalMarginY
78
94
  const outer = createOvalPath({
79
95
  centerX,
80
96
  centerY,
@@ -17,6 +17,7 @@ export const addPillHoleWithRectPad = (
17
17
  includeCopper,
18
18
  includeSoldermask,
19
19
  globalCopperSoldermaskMarginAdjustment,
20
+ solderMaskMarginPercent,
20
21
  includeLayers,
21
22
  } = ctx
22
23
  const centerX = platedHole.x + origin.x
@@ -54,14 +55,24 @@ export const addPillHoleWithRectPad = (
54
55
 
55
56
  // Add soldermask opening if drawing soldermask
56
57
  if (includeSoldermask) {
57
- const smPadWidth =
58
- padWidth +
59
- 2 * globalCopperSoldermaskMarginAdjustment +
60
- (platedHole.soldermask_margin ?? 0)
61
- const smPadHeight =
62
- padHeight +
63
- 2 * globalCopperSoldermaskMarginAdjustment +
64
- (platedHole.soldermask_margin ?? 0)
58
+ // Percent margin is additive and may be negative.
59
+ // Absolute per-element margin and global adjustment are always applied.
60
+ const percentMarginX = (solderMaskMarginPercent / 100) * padWidth
61
+ const percentMarginY = (solderMaskMarginPercent / 100) * padHeight
62
+ const totalMarginX = Math.max(
63
+ globalCopperSoldermaskMarginAdjustment +
64
+ (platedHole.soldermask_margin ?? 0) +
65
+ percentMarginX,
66
+ -padWidth / 2,
67
+ )
68
+ const totalMarginY = Math.max(
69
+ globalCopperSoldermaskMarginAdjustment +
70
+ (platedHole.soldermask_margin ?? 0) +
71
+ percentMarginY,
72
+ -padHeight / 2,
73
+ )
74
+ const smPadWidth = padWidth + 2 * totalMarginX
75
+ const smPadHeight = padHeight + 2 * totalMarginY
65
76
  const smPadPath = createRoundedRectPath({
66
77
  centerX,
67
78
  centerY,
@@ -17,6 +17,7 @@ export const addPcbPlatedHolePill = (
17
17
  includeCopper,
18
18
  includeSoldermask,
19
19
  globalCopperSoldermaskMarginAdjustment,
20
+ solderMaskMarginPercent,
20
21
  includeLayers,
21
22
  } = ctx
22
23
  const centerX = platedHole.x + origin.x
@@ -65,14 +66,26 @@ export const addPcbPlatedHolePill = (
65
66
  platedHole.outer_height > 0 &&
66
67
  includeSoldermask
67
68
  ) {
68
- const smWidth =
69
- platedHole.outer_width +
70
- 2 * globalCopperSoldermaskMarginAdjustment +
71
- (platedHole.soldermask_margin ?? 0)
72
- const smHeight =
73
- platedHole.outer_height +
74
- 2 * globalCopperSoldermaskMarginAdjustment +
75
- (platedHole.soldermask_margin ?? 0)
69
+ // Percent margin is additive and may be negative.
70
+ // Absolute per-element margin and global adjustment are always applied.
71
+ const percentMarginX =
72
+ (solderMaskMarginPercent / 100) * platedHole.outer_width
73
+ const percentMarginY =
74
+ (solderMaskMarginPercent / 100) * platedHole.outer_height
75
+ const totalMarginX = Math.max(
76
+ globalCopperSoldermaskMarginAdjustment +
77
+ (platedHole.soldermask_margin ?? 0) +
78
+ percentMarginX,
79
+ -platedHole.outer_width / 2,
80
+ )
81
+ const totalMarginY = Math.max(
82
+ globalCopperSoldermaskMarginAdjustment +
83
+ (platedHole.soldermask_margin ?? 0) +
84
+ percentMarginY,
85
+ -platedHole.outer_height / 2,
86
+ )
87
+ const smWidth = platedHole.outer_width + 2 * totalMarginX
88
+ const smHeight = platedHole.outer_height + 2 * totalMarginY
76
89
  const outer = createPillPath({
77
90
  centerX,
78
91
  centerY,
@@ -17,6 +17,7 @@ export const addRotatedPillHoleWithRectPad = (
17
17
  includeCopper,
18
18
  includeSoldermask,
19
19
  globalCopperSoldermaskMarginAdjustment,
20
+ solderMaskMarginPercent,
20
21
  includeLayers,
21
22
  } = ctx
22
23
  const centerX = platedHole.x + origin.x
@@ -57,14 +58,24 @@ export const addRotatedPillHoleWithRectPad = (
57
58
 
58
59
  // Add soldermask opening if drawing soldermask
59
60
  if (includeSoldermask) {
60
- const smPadWidth =
61
- padWidth +
62
- 2 * globalCopperSoldermaskMarginAdjustment +
63
- (platedHole.soldermask_margin ?? 0)
64
- const smPadHeight =
65
- padHeight +
66
- 2 * globalCopperSoldermaskMarginAdjustment +
67
- (platedHole.soldermask_margin ?? 0)
61
+ // Percent margin is additive and may be negative.
62
+ // Absolute per-element margin and global adjustment are always applied.
63
+ const percentMarginX = (solderMaskMarginPercent / 100) * padWidth
64
+ const percentMarginY = (solderMaskMarginPercent / 100) * padHeight
65
+ const totalMarginX = Math.max(
66
+ globalCopperSoldermaskMarginAdjustment +
67
+ (platedHole.soldermask_margin ?? 0) +
68
+ percentMarginX,
69
+ -padWidth / 2,
70
+ )
71
+ const totalMarginY = Math.max(
72
+ globalCopperSoldermaskMarginAdjustment +
73
+ (platedHole.soldermask_margin ?? 0) +
74
+ percentMarginY,
75
+ -padHeight / 2,
76
+ )
77
+ const smPadWidth = padWidth + 2 * totalMarginX
78
+ const smPadHeight = padHeight + 2 * totalMarginY
68
79
  const smPadPath = createRoundedRectPath({
69
80
  centerX,
70
81
  centerY,
@@ -15,6 +15,7 @@ export const addCircleSmtPad = (
15
15
  includeCopper,
16
16
  includeSoldermask,
17
17
  globalCopperSoldermaskMarginAdjustment,
18
+ solderMaskMarginPercent,
18
19
  includeLayers,
19
20
  } = ctx
20
21
 
@@ -51,10 +52,26 @@ export const addCircleSmtPad = (
51
52
 
52
53
  // Add soldermask opening if drawing soldermask
53
54
  if (includeSoldermask) {
54
- const smRadius =
55
- outerRadius +
55
+ // Percent margin is additive and may be negative.
56
+ // Absolute per-element margin and global adjustment are always applied.
57
+ const elementWidth = 2 * outerRadius
58
+ const elementHeight = 2 * outerRadius
59
+ const percentMarginX = (solderMaskMarginPercent / 100) * elementWidth
60
+ const percentMarginY = (solderMaskMarginPercent / 100) * elementHeight
61
+ const totalMarginX = Math.max(
56
62
  globalCopperSoldermaskMarginAdjustment +
57
- (smtPad.soldermask_margin ?? 0)
63
+ (smtPad.soldermask_margin ?? 0) +
64
+ percentMarginX,
65
+ -elementWidth / 2,
66
+ )
67
+ const totalMarginY = Math.max(
68
+ globalCopperSoldermaskMarginAdjustment +
69
+ (smtPad.soldermask_margin ?? 0) +
70
+ percentMarginY,
71
+ -elementHeight / 2,
72
+ )
73
+ // Since symmetric, use totalMarginX (same as totalMarginY)
74
+ const smRadius = outerRadius + totalMarginX
58
75
  const outer = createCirclePath({
59
76
  centerX,
60
77
  centerY,