circuit-to-canvas 0.0.44 → 0.0.46

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 (28) hide show
  1. package/dist/index.js +407 -182
  2. package/lib/drawer/CircuitToCanvasDrawer.ts +1 -5
  3. package/lib/drawer/elements/pcb-copper-text.ts +23 -37
  4. package/lib/drawer/elements/pcb-hole.ts +248 -61
  5. package/lib/drawer/elements/pcb-plated-hole.ts +194 -102
  6. package/lib/drawer/elements/pcb-smtpad.ts +14 -17
  7. package/package.json +1 -1
  8. package/tests/board-snapshot/__snapshots__/usb-c-flashlight-board.snap.png +0 -0
  9. package/tests/elements/__snapshots__/board-with-elements.snap.png +0 -0
  10. package/tests/elements/__snapshots__/custom-outline-board.snap.png +0 -0
  11. package/tests/elements/__snapshots__/pcb-board.snap.png +0 -0
  12. package/tests/elements/__snapshots__/pcb-comprehensive-soldermask-margin.snap.png +0 -0
  13. package/tests/elements/__snapshots__/pcb-copper-text-knockout.snap.png +0 -0
  14. package/tests/elements/__snapshots__/pcb-fabrication-note-dimension.snap.png +0 -0
  15. package/tests/elements/__snapshots__/pcb-hole-soldermask-margin.snap.png +0 -0
  16. package/tests/elements/__snapshots__/pcb-keepout-layer-filter.snap.png +0 -0
  17. package/tests/elements/__snapshots__/pcb-keepout-multiple-layers.snap.png +0 -0
  18. package/tests/elements/__snapshots__/pcb-keepout-rect-and-circle.snap.png +0 -0
  19. package/tests/elements/__snapshots__/pcb-keepout-with-group-id.snap.png +0 -0
  20. package/tests/elements/__snapshots__/pcb-note-dimension-with-offset.snap.png +0 -0
  21. package/tests/elements/__snapshots__/pcb-plated-hole-soldermask-margin.snap.png +0 -0
  22. package/tests/elements/__snapshots__/pcb-silkscreen-oval.snap.png +0 -0
  23. package/tests/elements/__snapshots__/pcb-smtpad-soldermask-margin.snap.png +0 -0
  24. package/tests/elements/pcb-comprehensive-soldermask-margin.test.ts +330 -0
  25. package/tests/elements/pcb-hole-soldermask-margin.test.ts +5 -5
  26. package/tests/elements/pcb-plated-hole-soldermask-margin.test.ts +8 -8
  27. package/tests/elements/pcb-smtpad-soldermask-margin.test.ts +0 -6
  28. package/tests/shapes/__snapshots__/dimension-line.snap.png +0 -0
package/dist/index.js CHANGED
@@ -464,8 +464,9 @@ function getSoldermaskColor(layers, colorMap) {
464
464
  }
465
465
  function drawPcbPlatedHole(params) {
466
466
  const { ctx, hole, realToCanvasMat, colorMap } = params;
467
- const hasSoldermask = hole.is_covered_with_solder_mask === true && hole.soldermask_margin !== void 0 && hole.soldermask_margin !== 0;
468
- const margin = hasSoldermask ? hole.soldermask_margin : 0;
467
+ const isCoveredWithSoldermask = hole.is_covered_with_solder_mask === true;
468
+ const margin = isCoveredWithSoldermask ? 0 : hole.soldermask_margin ?? 0;
469
+ const hasSoldermask = !isCoveredWithSoldermask && hole.soldermask_margin !== void 0 && hole.soldermask_margin !== 0;
469
470
  const soldermaskRingColor = getSoldermaskColor(hole.layers, colorMap);
470
471
  const positiveMarginColor = colorMap.substrate;
471
472
  const copperColor = colorMap.copper.top;
@@ -497,13 +498,24 @@ function drawPcbPlatedHole(params) {
497
498
  copperColor
498
499
  );
499
500
  }
500
- drawCircle({
501
- ctx,
502
- center: { x: hole.x, y: hole.y },
503
- radius: hole.hole_diameter / 2,
504
- fill: colorMap.drill,
505
- realToCanvasMat
506
- });
501
+ if (isCoveredWithSoldermask) {
502
+ drawCircle({
503
+ ctx,
504
+ center: { x: hole.x, y: hole.y },
505
+ radius: hole.outer_diameter / 2,
506
+ fill: soldermaskRingColor,
507
+ realToCanvasMat
508
+ });
509
+ }
510
+ if (!isCoveredWithSoldermask) {
511
+ drawCircle({
512
+ ctx,
513
+ center: { x: hole.x, y: hole.y },
514
+ radius: hole.hole_diameter / 2,
515
+ fill: colorMap.drill,
516
+ realToCanvasMat
517
+ });
518
+ }
507
519
  return;
508
520
  }
509
521
  if (hole.shape === "oval") {
@@ -540,15 +552,28 @@ function drawPcbPlatedHole(params) {
540
552
  copperColor
541
553
  );
542
554
  }
543
- drawOval({
544
- ctx,
545
- center: { x: hole.x, y: hole.y },
546
- radius_x: hole.hole_width / 2,
547
- radius_y: hole.hole_height / 2,
548
- fill: colorMap.drill,
549
- realToCanvasMat,
550
- rotation: hole.ccw_rotation
551
- });
555
+ if (isCoveredWithSoldermask) {
556
+ drawOval({
557
+ ctx,
558
+ center: { x: hole.x, y: hole.y },
559
+ radius_x: hole.outer_width / 2,
560
+ radius_y: hole.outer_height / 2,
561
+ fill: soldermaskRingColor,
562
+ realToCanvasMat,
563
+ rotation: hole.ccw_rotation
564
+ });
565
+ }
566
+ if (!isCoveredWithSoldermask) {
567
+ drawOval({
568
+ ctx,
569
+ center: { x: hole.x, y: hole.y },
570
+ radius_x: hole.hole_width / 2,
571
+ radius_y: hole.hole_height / 2,
572
+ fill: colorMap.drill,
573
+ realToCanvasMat,
574
+ rotation: hole.ccw_rotation
575
+ });
576
+ }
552
577
  return;
553
578
  }
554
579
  if (hole.shape === "pill") {
@@ -585,15 +610,28 @@ function drawPcbPlatedHole(params) {
585
610
  copperColor
586
611
  );
587
612
  }
588
- drawPill({
589
- ctx,
590
- center: { x: hole.x, y: hole.y },
591
- width: hole.hole_width,
592
- height: hole.hole_height,
593
- fill: colorMap.drill,
594
- realToCanvasMat,
595
- rotation: hole.ccw_rotation
596
- });
613
+ if (isCoveredWithSoldermask) {
614
+ drawPill({
615
+ ctx,
616
+ center: { x: hole.x, y: hole.y },
617
+ width: hole.outer_width,
618
+ height: hole.outer_height,
619
+ fill: soldermaskRingColor,
620
+ realToCanvasMat,
621
+ rotation: hole.ccw_rotation
622
+ });
623
+ }
624
+ if (!isCoveredWithSoldermask) {
625
+ drawPill({
626
+ ctx,
627
+ center: { x: hole.x, y: hole.y },
628
+ width: hole.hole_width,
629
+ height: hole.hole_height,
630
+ fill: colorMap.drill,
631
+ realToCanvasMat,
632
+ rotation: hole.ccw_rotation
633
+ });
634
+ }
597
635
  return;
598
636
  }
599
637
  if (hole.shape === "circular_hole_with_rect_pad") {
@@ -631,15 +669,28 @@ function drawPcbPlatedHole(params) {
631
669
  copperColor
632
670
  );
633
671
  }
634
- const holeX = hole.x + (hole.hole_offset_x ?? 0);
635
- const holeY = hole.y + (hole.hole_offset_y ?? 0);
636
- drawCircle({
637
- ctx,
638
- center: { x: holeX, y: holeY },
639
- radius: hole.hole_diameter / 2,
640
- fill: colorMap.drill,
641
- realToCanvasMat
642
- });
672
+ if (isCoveredWithSoldermask) {
673
+ drawRect({
674
+ ctx,
675
+ center: { x: hole.x, y: hole.y },
676
+ width: hole.rect_pad_width,
677
+ height: hole.rect_pad_height,
678
+ fill: soldermaskRingColor,
679
+ realToCanvasMat,
680
+ borderRadius: hole.rect_border_radius ?? 0
681
+ });
682
+ }
683
+ if (!isCoveredWithSoldermask) {
684
+ const holeX = hole.x + (hole.hole_offset_x ?? 0);
685
+ const holeY = hole.y + (hole.hole_offset_y ?? 0);
686
+ drawCircle({
687
+ ctx,
688
+ center: { x: holeX, y: holeY },
689
+ radius: hole.hole_diameter / 2,
690
+ fill: colorMap.drill,
691
+ realToCanvasMat
692
+ });
693
+ }
643
694
  return;
644
695
  }
645
696
  if (hole.shape === "pill_hole_with_rect_pad") {
@@ -677,16 +728,29 @@ function drawPcbPlatedHole(params) {
677
728
  copperColor
678
729
  );
679
730
  }
680
- const holeX = hole.x + (hole.hole_offset_x ?? 0);
681
- const holeY = hole.y + (hole.hole_offset_y ?? 0);
682
- drawPill({
683
- ctx,
684
- center: { x: holeX, y: holeY },
685
- width: hole.hole_width,
686
- height: hole.hole_height,
687
- fill: colorMap.drill,
688
- realToCanvasMat
689
- });
731
+ if (isCoveredWithSoldermask) {
732
+ drawRect({
733
+ ctx,
734
+ center: { x: hole.x, y: hole.y },
735
+ width: hole.rect_pad_width,
736
+ height: hole.rect_pad_height,
737
+ fill: soldermaskRingColor,
738
+ realToCanvasMat,
739
+ borderRadius: hole.rect_border_radius ?? 0
740
+ });
741
+ }
742
+ if (!isCoveredWithSoldermask) {
743
+ const holeX = hole.x + (hole.hole_offset_x ?? 0);
744
+ const holeY = hole.y + (hole.hole_offset_y ?? 0);
745
+ drawPill({
746
+ ctx,
747
+ center: { x: holeX, y: holeY },
748
+ width: hole.hole_width,
749
+ height: hole.hole_height,
750
+ fill: colorMap.drill,
751
+ realToCanvasMat
752
+ });
753
+ }
690
754
  return;
691
755
  }
692
756
  if (hole.shape === "rotated_pill_hole_with_rect_pad") {
@@ -726,17 +790,31 @@ function drawPcbPlatedHole(params) {
726
790
  copperColor
727
791
  );
728
792
  }
729
- const holeX = hole.x + (hole.hole_offset_x ?? 0);
730
- const holeY = hole.y + (hole.hole_offset_y ?? 0);
731
- drawPill({
732
- ctx,
733
- center: { x: holeX, y: holeY },
734
- width: hole.hole_width,
735
- height: hole.hole_height,
736
- fill: colorMap.drill,
737
- realToCanvasMat,
738
- rotation: hole.hole_ccw_rotation
739
- });
793
+ if (isCoveredWithSoldermask) {
794
+ drawRect({
795
+ ctx,
796
+ center: { x: hole.x, y: hole.y },
797
+ width: hole.rect_pad_width,
798
+ height: hole.rect_pad_height,
799
+ fill: soldermaskRingColor,
800
+ realToCanvasMat,
801
+ borderRadius: hole.rect_border_radius ?? 0,
802
+ rotation: hole.rect_ccw_rotation
803
+ });
804
+ }
805
+ if (!isCoveredWithSoldermask) {
806
+ const holeX = hole.x + (hole.hole_offset_x ?? 0);
807
+ const holeY = hole.y + (hole.hole_offset_y ?? 0);
808
+ drawPill({
809
+ ctx,
810
+ center: { x: holeX, y: holeY },
811
+ width: hole.hole_width,
812
+ height: hole.hole_height,
813
+ fill: colorMap.drill,
814
+ realToCanvasMat,
815
+ rotation: hole.hole_ccw_rotation
816
+ });
817
+ }
740
818
  return;
741
819
  }
742
820
  if (hole.shape === "hole_with_polygon_pad") {
@@ -753,44 +831,46 @@ function drawPcbPlatedHole(params) {
753
831
  realToCanvasMat
754
832
  });
755
833
  }
756
- const holeX = hole.x + (hole.hole_offset_x ?? 0);
757
- const holeY = hole.y + (hole.hole_offset_y ?? 0);
758
- const holeShape = hole.hole_shape;
759
- if (holeShape === "circle") {
760
- drawCircle({
761
- ctx,
762
- center: { x: holeX, y: holeY },
763
- radius: (hole.hole_diameter ?? 0) / 2,
764
- fill: colorMap.drill,
765
- realToCanvasMat
766
- });
767
- } else if (holeShape === "oval") {
768
- drawOval({
769
- ctx,
770
- center: { x: holeX, y: holeY },
771
- radius_x: (hole.hole_width ?? 0) / 2,
772
- radius_y: (hole.hole_height ?? 0) / 2,
773
- fill: colorMap.drill,
774
- realToCanvasMat
775
- });
776
- } else if (holeShape === "pill") {
777
- drawPill({
778
- ctx,
779
- center: { x: holeX, y: holeY },
780
- width: hole.hole_width ?? 0,
781
- height: hole.hole_height ?? 0,
782
- fill: colorMap.drill,
783
- realToCanvasMat
784
- });
785
- } else if (holeShape === "rotated_pill") {
786
- drawPill({
787
- ctx,
788
- center: { x: holeX, y: holeY },
789
- width: hole.hole_width ?? 0,
790
- height: hole.hole_height ?? 0,
791
- fill: colorMap.drill,
792
- realToCanvasMat
793
- });
834
+ if (!isCoveredWithSoldermask) {
835
+ const holeX = hole.x + (hole.hole_offset_x ?? 0);
836
+ const holeY = hole.y + (hole.hole_offset_y ?? 0);
837
+ const holeShape = hole.hole_shape;
838
+ if (holeShape === "circle") {
839
+ drawCircle({
840
+ ctx,
841
+ center: { x: holeX, y: holeY },
842
+ radius: (hole.hole_diameter ?? 0) / 2,
843
+ fill: colorMap.drill,
844
+ realToCanvasMat
845
+ });
846
+ } else if (holeShape === "oval") {
847
+ drawOval({
848
+ ctx,
849
+ center: { x: holeX, y: holeY },
850
+ radius_x: (hole.hole_width ?? 0) / 2,
851
+ radius_y: (hole.hole_height ?? 0) / 2,
852
+ fill: colorMap.drill,
853
+ realToCanvasMat
854
+ });
855
+ } else if (holeShape === "pill") {
856
+ drawPill({
857
+ ctx,
858
+ center: { x: holeX, y: holeY },
859
+ width: hole.hole_width ?? 0,
860
+ height: hole.hole_height ?? 0,
861
+ fill: colorMap.drill,
862
+ realToCanvasMat
863
+ });
864
+ } else if (holeShape === "rotated_pill") {
865
+ drawPill({
866
+ ctx,
867
+ center: { x: holeX, y: holeY },
868
+ width: hole.hole_width ?? 0,
869
+ height: hole.hole_height ?? 0,
870
+ fill: colorMap.drill,
871
+ realToCanvasMat
872
+ });
873
+ }
794
874
  }
795
875
  return;
796
876
  }
@@ -824,9 +904,12 @@ function getRotation(hole) {
824
904
  }
825
905
  function drawPcbHole(params) {
826
906
  const { ctx, hole, realToCanvasMat, colorMap } = params;
827
- const hasSoldermask = hole.is_covered_with_solder_mask === true && hole.soldermask_margin !== void 0 && hole.soldermask_margin > 0;
828
- const margin = hasSoldermask ? hole.soldermask_margin : 0;
907
+ const isCoveredWithSoldermask = hole.is_covered_with_solder_mask === true;
908
+ const margin = isCoveredWithSoldermask ? 0 : hole.soldermask_margin ?? 0;
909
+ const hasSoldermask = !isCoveredWithSoldermask && hole.soldermask_margin !== void 0 && hole.soldermask_margin !== 0;
829
910
  const positiveMarginColor = colorMap.substrate;
911
+ const soldermaskOverlayColor = colorMap.soldermask.top;
912
+ const soldermaskRingColor = colorMap.soldermask.top;
830
913
  if (hole.hole_shape === "circle") {
831
914
  if (hasSoldermask && margin > 0) {
832
915
  drawCircle({
@@ -837,13 +920,35 @@ function drawPcbHole(params) {
837
920
  realToCanvasMat
838
921
  });
839
922
  }
840
- drawCircle({
841
- ctx,
842
- center: { x: hole.x, y: hole.y },
843
- radius: hole.hole_diameter / 2,
844
- fill: colorMap.drill,
845
- realToCanvasMat
846
- });
923
+ if (!isCoveredWithSoldermask) {
924
+ drawCircle({
925
+ ctx,
926
+ center: { x: hole.x, y: hole.y },
927
+ radius: hole.hole_diameter / 2,
928
+ fill: colorMap.drill,
929
+ realToCanvasMat
930
+ });
931
+ if (hasSoldermask && margin < 0) {
932
+ drawSoldermaskRingForCircle(
933
+ ctx,
934
+ { x: hole.x, y: hole.y },
935
+ hole.hole_diameter / 2,
936
+ margin,
937
+ realToCanvasMat,
938
+ soldermaskRingColor,
939
+ colorMap.drill
940
+ );
941
+ }
942
+ }
943
+ if (isCoveredWithSoldermask) {
944
+ drawCircle({
945
+ ctx,
946
+ center: { x: hole.x, y: hole.y },
947
+ radius: hole.hole_diameter / 2,
948
+ fill: soldermaskOverlayColor,
949
+ realToCanvasMat
950
+ });
951
+ }
847
952
  return;
848
953
  }
849
954
  if (hole.hole_shape === "square") {
@@ -859,15 +964,42 @@ function drawPcbHole(params) {
859
964
  rotation
860
965
  });
861
966
  }
862
- drawRect({
863
- ctx,
864
- center: { x: hole.x, y: hole.y },
865
- width: hole.hole_diameter,
866
- height: hole.hole_diameter,
867
- fill: colorMap.drill,
868
- realToCanvasMat,
869
- rotation
870
- });
967
+ if (!isCoveredWithSoldermask) {
968
+ drawRect({
969
+ ctx,
970
+ center: { x: hole.x, y: hole.y },
971
+ width: hole.hole_diameter,
972
+ height: hole.hole_diameter,
973
+ fill: colorMap.drill,
974
+ realToCanvasMat,
975
+ rotation
976
+ });
977
+ if (hasSoldermask && margin < 0) {
978
+ drawSoldermaskRingForRect(
979
+ ctx,
980
+ { x: hole.x, y: hole.y },
981
+ hole.hole_diameter,
982
+ hole.hole_diameter,
983
+ margin,
984
+ 0,
985
+ rotation,
986
+ realToCanvasMat,
987
+ soldermaskRingColor,
988
+ colorMap.drill
989
+ );
990
+ }
991
+ }
992
+ if (isCoveredWithSoldermask) {
993
+ drawRect({
994
+ ctx,
995
+ center: { x: hole.x, y: hole.y },
996
+ width: hole.hole_diameter,
997
+ height: hole.hole_diameter,
998
+ fill: soldermaskOverlayColor,
999
+ realToCanvasMat,
1000
+ rotation
1001
+ });
1002
+ }
871
1003
  return;
872
1004
  }
873
1005
  if (hole.hole_shape === "oval") {
@@ -883,15 +1015,41 @@ function drawPcbHole(params) {
883
1015
  rotation
884
1016
  });
885
1017
  }
886
- drawOval({
887
- ctx,
888
- center: { x: hole.x, y: hole.y },
889
- radius_x: hole.hole_width / 2,
890
- radius_y: hole.hole_height / 2,
891
- fill: colorMap.drill,
892
- realToCanvasMat,
893
- rotation
894
- });
1018
+ if (!isCoveredWithSoldermask) {
1019
+ drawOval({
1020
+ ctx,
1021
+ center: { x: hole.x, y: hole.y },
1022
+ radius_x: hole.hole_width / 2,
1023
+ radius_y: hole.hole_height / 2,
1024
+ fill: colorMap.drill,
1025
+ realToCanvasMat,
1026
+ rotation
1027
+ });
1028
+ if (hasSoldermask && margin < 0) {
1029
+ drawSoldermaskRingForOval(
1030
+ ctx,
1031
+ { x: hole.x, y: hole.y },
1032
+ hole.hole_width / 2,
1033
+ hole.hole_height / 2,
1034
+ margin,
1035
+ rotation,
1036
+ realToCanvasMat,
1037
+ soldermaskRingColor,
1038
+ colorMap.drill
1039
+ );
1040
+ }
1041
+ }
1042
+ if (isCoveredWithSoldermask) {
1043
+ drawOval({
1044
+ ctx,
1045
+ center: { x: hole.x, y: hole.y },
1046
+ radius_x: hole.hole_width / 2,
1047
+ radius_y: hole.hole_height / 2,
1048
+ fill: soldermaskOverlayColor,
1049
+ realToCanvasMat,
1050
+ rotation
1051
+ });
1052
+ }
895
1053
  return;
896
1054
  }
897
1055
  if (hole.hole_shape === "rect") {
@@ -907,15 +1065,42 @@ function drawPcbHole(params) {
907
1065
  rotation
908
1066
  });
909
1067
  }
910
- drawRect({
911
- ctx,
912
- center: { x: hole.x, y: hole.y },
913
- width: hole.hole_width,
914
- height: hole.hole_height,
915
- fill: colorMap.drill,
916
- realToCanvasMat,
917
- rotation
918
- });
1068
+ if (!isCoveredWithSoldermask) {
1069
+ drawRect({
1070
+ ctx,
1071
+ center: { x: hole.x, y: hole.y },
1072
+ width: hole.hole_width,
1073
+ height: hole.hole_height,
1074
+ fill: colorMap.drill,
1075
+ realToCanvasMat,
1076
+ rotation
1077
+ });
1078
+ if (hasSoldermask && margin < 0) {
1079
+ drawSoldermaskRingForRect(
1080
+ ctx,
1081
+ { x: hole.x, y: hole.y },
1082
+ hole.hole_width,
1083
+ hole.hole_height,
1084
+ margin,
1085
+ 0,
1086
+ rotation,
1087
+ realToCanvasMat,
1088
+ soldermaskRingColor,
1089
+ colorMap.drill
1090
+ );
1091
+ }
1092
+ }
1093
+ if (isCoveredWithSoldermask) {
1094
+ drawRect({
1095
+ ctx,
1096
+ center: { x: hole.x, y: hole.y },
1097
+ width: hole.hole_width,
1098
+ height: hole.hole_height,
1099
+ fill: soldermaskOverlayColor,
1100
+ realToCanvasMat,
1101
+ rotation
1102
+ });
1103
+ }
919
1104
  return;
920
1105
  }
921
1106
  if (hole.hole_shape === "pill") {
@@ -931,15 +1116,41 @@ function drawPcbHole(params) {
931
1116
  rotation
932
1117
  });
933
1118
  }
934
- drawPill({
935
- ctx,
936
- center: { x: hole.x, y: hole.y },
937
- width: hole.hole_width,
938
- height: hole.hole_height,
939
- fill: colorMap.drill,
940
- realToCanvasMat,
941
- rotation
942
- });
1119
+ if (!isCoveredWithSoldermask) {
1120
+ drawPill({
1121
+ ctx,
1122
+ center: { x: hole.x, y: hole.y },
1123
+ width: hole.hole_width,
1124
+ height: hole.hole_height,
1125
+ fill: colorMap.drill,
1126
+ realToCanvasMat,
1127
+ rotation
1128
+ });
1129
+ if (hasSoldermask && margin < 0) {
1130
+ drawSoldermaskRingForPill(
1131
+ ctx,
1132
+ { x: hole.x, y: hole.y },
1133
+ hole.hole_width,
1134
+ hole.hole_height,
1135
+ margin,
1136
+ rotation,
1137
+ realToCanvasMat,
1138
+ soldermaskRingColor,
1139
+ colorMap.drill
1140
+ );
1141
+ }
1142
+ }
1143
+ if (isCoveredWithSoldermask) {
1144
+ drawPill({
1145
+ ctx,
1146
+ center: { x: hole.x, y: hole.y },
1147
+ width: hole.hole_width,
1148
+ height: hole.hole_height,
1149
+ fill: soldermaskOverlayColor,
1150
+ realToCanvasMat,
1151
+ rotation
1152
+ });
1153
+ }
943
1154
  return;
944
1155
  }
945
1156
  if (hole.hole_shape === "rotated_pill") {
@@ -955,15 +1166,41 @@ function drawPcbHole(params) {
955
1166
  rotation
956
1167
  });
957
1168
  }
958
- drawPill({
959
- ctx,
960
- center: { x: hole.x, y: hole.y },
961
- width: hole.hole_width,
962
- height: hole.hole_height,
963
- fill: colorMap.drill,
964
- realToCanvasMat,
965
- rotation
966
- });
1169
+ if (!isCoveredWithSoldermask) {
1170
+ drawPill({
1171
+ ctx,
1172
+ center: { x: hole.x, y: hole.y },
1173
+ width: hole.hole_width,
1174
+ height: hole.hole_height,
1175
+ fill: colorMap.drill,
1176
+ realToCanvasMat,
1177
+ rotation
1178
+ });
1179
+ if (hasSoldermask && margin < 0) {
1180
+ drawSoldermaskRingForPill(
1181
+ ctx,
1182
+ { x: hole.x, y: hole.y },
1183
+ hole.hole_width,
1184
+ hole.hole_height,
1185
+ margin,
1186
+ rotation,
1187
+ realToCanvasMat,
1188
+ soldermaskRingColor,
1189
+ colorMap.drill
1190
+ );
1191
+ }
1192
+ }
1193
+ if (isCoveredWithSoldermask) {
1194
+ drawPill({
1195
+ ctx,
1196
+ center: { x: hole.x, y: hole.y },
1197
+ width: hole.hole_width,
1198
+ height: hole.hole_height,
1199
+ fill: soldermaskOverlayColor,
1200
+ realToCanvasMat,
1201
+ rotation
1202
+ });
1203
+ }
967
1204
  return;
968
1205
  }
969
1206
  }
@@ -982,13 +1219,13 @@ function drawPcbSmtPad(params) {
982
1219
  const { ctx, pad, realToCanvasMat, colorMap } = params;
983
1220
  const color = layerToColor(pad.layer, colorMap);
984
1221
  const isCoveredWithSoldermask = pad.is_covered_with_solder_mask === true;
985
- const margin = isCoveredWithSoldermask && pad.soldermask_margin !== void 0 ? pad.soldermask_margin : 0;
986
- const hasSoldermask = isCoveredWithSoldermask && pad.soldermask_margin !== void 0 && pad.soldermask_margin !== 0;
1222
+ const margin = isCoveredWithSoldermask ? 0 : pad.soldermask_margin ?? 0;
1223
+ const hasSoldermask = !isCoveredWithSoldermask && pad.soldermask_margin !== void 0 && pad.soldermask_margin !== 0;
987
1224
  const soldermaskRingColor = getSoldermaskColor2(pad.layer, colorMap);
988
1225
  const positiveMarginColor = colorMap.substrate;
989
1226
  const soldermaskOverlayColor = getSoldermaskColor2(pad.layer, colorMap);
990
1227
  if (pad.shape === "rect") {
991
- if (isCoveredWithSoldermask && margin >= 0) {
1228
+ if (hasSoldermask && margin > 0) {
992
1229
  drawRect({
993
1230
  ctx,
994
1231
  center: { x: pad.x, y: pad.y },
@@ -1036,7 +1273,7 @@ function drawPcbSmtPad(params) {
1036
1273
  return;
1037
1274
  }
1038
1275
  if (pad.shape === "rotated_rect") {
1039
- if (isCoveredWithSoldermask && margin >= 0) {
1276
+ if (hasSoldermask && margin > 0) {
1040
1277
  drawRect({
1041
1278
  ctx,
1042
1279
  center: { x: pad.x, y: pad.y },
@@ -1087,7 +1324,7 @@ function drawPcbSmtPad(params) {
1087
1324
  return;
1088
1325
  }
1089
1326
  if (pad.shape === "circle") {
1090
- if (isCoveredWithSoldermask && margin >= 0) {
1327
+ if (hasSoldermask && margin > 0) {
1091
1328
  drawCircle({
1092
1329
  ctx,
1093
1330
  center: { x: pad.x, y: pad.y },
@@ -1126,7 +1363,7 @@ function drawPcbSmtPad(params) {
1126
1363
  return;
1127
1364
  }
1128
1365
  if (pad.shape === "pill") {
1129
- if (isCoveredWithSoldermask && margin >= 0) {
1366
+ if (hasSoldermask && margin > 0) {
1130
1367
  drawPill({
1131
1368
  ctx,
1132
1369
  center: { x: pad.x, y: pad.y },
@@ -1170,7 +1407,7 @@ function drawPcbSmtPad(params) {
1170
1407
  return;
1171
1408
  }
1172
1409
  if (pad.shape === "rotated_pill") {
1173
- if (isCoveredWithSoldermask && margin >= 0) {
1410
+ if (hasSoldermask && margin > 0) {
1174
1411
  drawPill({
1175
1412
  ctx,
1176
1413
  center: { x: pad.x, y: pad.y },
@@ -1843,9 +2080,6 @@ function drawPcbCopperPour(params) {
1843
2080
  // lib/drawer/elements/pcb-copper-text.ts
1844
2081
  import { applyToPoint as applyToPoint13 } from "transformation-matrix";
1845
2082
  var DEFAULT_PADDING = { left: 0.2, right: 0.2, top: 0.2, bottom: 0.2 };
1846
- function layerToCopperColor(layer, colorMap) {
1847
- return colorMap.copper[layer] ?? colorMap.copper.top;
1848
- }
1849
2083
  function mapAnchorAlignment2(alignment) {
1850
2084
  if (!alignment) return "center";
1851
2085
  if (alignment.includes("left")) return "center_left";
@@ -1867,13 +2101,11 @@ function drawPcbCopperText(params) {
1867
2101
  ...DEFAULT_PADDING,
1868
2102
  ...text.knockout_padding
1869
2103
  };
1870
- const textColor = layerToCopperColor(text.layer, colorMap);
2104
+ const textColor = colorMap.copper[text.layer] ?? colorMap.copper.top;
1871
2105
  const layout = getAlphabetLayout(content, fontSize);
1872
2106
  const totalWidth = layout.width + layout.strokeWidth;
1873
2107
  const alignment = mapAnchorAlignment2(text.anchor_alignment);
1874
2108
  const startPos = getTextStartPosition(alignment, layout);
1875
- const startX = startPos.x;
1876
- const startY = startPos.y;
1877
2109
  ctx.save();
1878
2110
  ctx.translate(x, y);
1879
2111
  if (text.is_mirrored) ctx.scale(-1, 1);
@@ -1886,29 +2118,22 @@ function drawPcbCopperText(params) {
1886
2118
  const paddingRight = padding.right * scale2;
1887
2119
  const paddingTop = padding.top * scale2;
1888
2120
  const paddingBottom = padding.bottom * scale2;
1889
- const textBoxTop = startY - layout.strokeWidth / 2;
1890
- const textBoxBottom = startY + layout.height + layout.strokeWidth / 2;
1891
- const textBoxHeight = textBoxBottom - textBoxTop;
1892
- const xOffset = startX - paddingLeft;
1893
- const yOffset = textBoxTop - paddingTop;
1894
- const knockoutWidth = totalWidth + paddingLeft + paddingRight;
1895
- const knockoutHeight = textBoxHeight + paddingTop + paddingBottom;
2121
+ const rectX = startPos.x - paddingLeft * 4;
2122
+ const rectY = startPos.y - paddingTop * 4;
2123
+ const rectWidth = totalWidth + paddingLeft * 2 + paddingRight * 2;
2124
+ const rectHeight = layout.height + layout.strokeWidth + paddingTop * 2 + paddingBottom * 2;
1896
2125
  ctx.fillStyle = textColor;
1897
- ctx.fillRect(xOffset, yOffset, knockoutWidth, knockoutHeight);
1898
- const previousCompositeOperation = ctx.globalCompositeOperation;
1899
- ctx.globalCompositeOperation = "destination-out";
1900
- ctx.fillStyle = "rgba(0,0,0,1)";
1901
- ctx.strokeStyle = "rgba(0,0,0,1)";
1902
- strokeAlphabetText({ ctx, text: content, fontSize, startX, startY });
1903
- if (previousCompositeOperation) {
1904
- ctx.globalCompositeOperation = previousCompositeOperation;
1905
- } else {
1906
- ctx.globalCompositeOperation = "source-over";
1907
- }
2126
+ ctx.fillRect(rectX, rectY, rectWidth, rectHeight);
1908
2127
  } else {
1909
2128
  ctx.strokeStyle = textColor;
1910
- strokeAlphabetText({ ctx, text: content, fontSize, startX, startY });
1911
2129
  }
2130
+ strokeAlphabetText({
2131
+ ctx,
2132
+ text: content,
2133
+ fontSize,
2134
+ startX: startPos.x,
2135
+ startY: startPos.y
2136
+ });
1912
2137
  ctx.restore();
1913
2138
  }
1914
2139
 
@@ -2367,7 +2592,7 @@ var CircuitToCanvasDrawer = class {
2367
2592
  (el) => el.type === "pcb_plated_hole" && el.is_covered_with_solder_mask === true
2368
2593
  );
2369
2594
  for (const element of elements) {
2370
- if (element.type === "pcb_board" && (hasSoldermaskPads || hasSoldermaskHoles || hasSoldermaskPlatedHoles)) {
2595
+ if (element.type === "pcb_board") {
2371
2596
  this.drawBoardWithSoldermask(element);
2372
2597
  } else {
2373
2598
  this.drawElement(element, options);