@@ -435,15 +435,45 @@ def get_all_drawings(self):
435435 return drawings
436436
437437 def parse_pad (self , pad ):
438- # type: (pcbnew.PAD) -> dict | None
439- layers_set = list (pad .GetLayerSet ().Seq ())
438+ # type: (pcbnew.PAD) -> list[dict]
439+ custom_padstack = False
440+ outer_layers = [(pcbnew .F_Cu , "F" ), (pcbnew .B_Cu , "B" )]
441+ if hasattr (pad , 'Padstack' ):
442+ padstack = pad .Padstack () # type: pcbnew.PADSTACK
443+ layers_set = list (padstack .LayerSet ().Seq ())
444+ custom_padstack = (
445+ padstack .Mode () != padstack .MODE_NORMAL or \
446+ padstack .UnconnectedLayerMode () == padstack .UNCONNECTED_LAYER_MODE_REMOVE_ALL
447+ )
448+ else :
449+ layers_set = list (pad .GetLayerSet ().Seq ())
440450 layers = []
441- if pcbnew .F_Cu in layers_set :
442- layers .append ("F" )
443- if pcbnew .B_Cu in layers_set :
444- layers .append ("B" )
451+ for layer , letter in outer_layers :
452+ if layer in layers_set :
453+ layers .append (letter )
454+ if not layers :
455+ return []
456+
457+ if custom_padstack :
458+ pads = []
459+ for layer , letter in outer_layers :
460+ if layer in layers_set and pad .FlashLayer (layer ):
461+ pad_dict = self .parse_pad_layer (pad , layer )
462+ pad_dict ["layers" ] = [letter ]
463+ pads .append (pad_dict )
464+ return pads
465+ else :
466+ pad_dict = self .parse_pad_layer (pad , layers_set [0 ])
467+ pad_dict ["layers" ] = layers
468+ return [pad_dict ]
469+
470+ def parse_pad_layer (self , pad , layer ):
471+ # type: (pcbnew.PAD, int) -> dict | None
445472 pos = self .normalize (pad .GetPosition ())
446- size = self .normalize (pad .GetSize ())
473+ try :
474+ size = self .normalize (pad .GetSize (layer ))
475+ except TypeError :
476+ size = self .normalize (pad .GetSize ())
447477 angle = self .normalize_angle (pad .GetOrientation ())
448478 shape_lookup = {
449479 pcbnew .PAD_SHAPE_RECT : "rect" ,
@@ -458,27 +488,36 @@ def parse_pad(self, pad):
458488 shape_lookup [pcbnew .PAD_SHAPE_CUSTOM ] = "custom"
459489 if hasattr (pcbnew , "PAD_SHAPE_CHAMFERED_RECT" ):
460490 shape_lookup [pcbnew .PAD_SHAPE_CHAMFERED_RECT ] = "chamfrect"
461- shape = shape_lookup .get (pad .GetShape (), "" )
491+ try :
492+ pad_shape = pad .GetShape (layer )
493+ except TypeError :
494+ pad_shape = pad .GetShape ()
495+ shape = shape_lookup .get (pad_shape , "" )
462496 if shape == "" :
463- self .logger .info ("Unsupported pad shape %s, skipping." ,
464- pad .GetShape ())
497+ self .logger .info ("Unsupported pad shape %s, skipping." , pad_shape )
465498 return None
466499 pad_dict = {
467- "layers" : layers ,
468500 "pos" : pos ,
469501 "size" : size ,
470502 "angle" : angle ,
471503 "shape" : shape
472504 }
473505 if shape == "custom" :
474- polygon_set = pad .GetCustomShapeAsPolygon ()
506+ polygon_set = pcbnew .SHAPE_POLY_SET ()
507+ try :
508+ pad .MergePrimitivesAsPolygon (layer , polygon_set )
509+ except TypeError :
510+ pad .MergePrimitivesAsPolygon (polygon_set )
475511 if polygon_set .HasHoles ():
476512 self .logger .warn ('Detected holes in custom pad polygons' )
477513 pad_dict ["polygons" ] = self .parse_poly_set (polygon_set )
478514 if shape == "trapezoid" :
479515 # treat trapezoid as custom shape
480516 pad_dict ["shape" ] = "custom"
481- delta = self .normalize (pad .GetDelta ())
517+ try :
518+ delta = self .normalize (pad .GetDelta (layer ))
519+ except TypeError :
520+ delta = self .normalize (pad .GetDelta ())
482521 pad_dict ["polygons" ] = [[
483522 [size [0 ] / 2 + delta [1 ] / 2 , size [1 ] / 2 - delta [0 ] / 2 ],
484523 [- size [0 ] / 2 - delta [1 ] / 2 , size [1 ] / 2 + delta [0 ] / 2 ],
@@ -487,10 +526,17 @@ def parse_pad(self, pad):
487526 ]]
488527
489528 if shape in ["roundrect" , "chamfrect" ]:
490- pad_dict ["radius" ] = pad .GetRoundRectCornerRadius () * 1e-6
529+ try :
530+ pad_dict ["radius" ] = pad .GetRoundRectCornerRadius (layer ) * 1e-6
531+ except TypeError :
532+ pad_dict ["radius" ] = pad .GetRoundRectCornerRadius () * 1e-6
491533 if shape == "chamfrect" :
492- pad_dict ["chamfpos" ] = pad .GetChamferPositions ()
493- pad_dict ["chamfratio" ] = pad .GetChamferRectRatio ()
534+ try :
535+ pad_dict ["chamfpos" ] = pad .GetChamferPositions (layer )
536+ pad_dict ["chamfratio" ] = pad .GetChamferRectRatio (layer )
537+ except TypeError :
538+ pad_dict ["chamfpos" ] = pad .GetChamferPositions ()
539+ pad_dict ["chamfratio" ] = pad .GetChamferRectRatio ()
494540 if hasattr (pcbnew , 'PAD_ATTRIB_PTH' ):
495541 through_hole_attributes = [pcbnew .PAD_ATTRIB_PTH ,
496542 pcbnew .PAD_ATTRIB_NPTH ]
@@ -507,7 +553,10 @@ def parse_pad(self, pad):
507553 else :
508554 pad_dict ["type" ] = "smd"
509555 if hasattr (pad , "GetOffset" ):
510- pad_dict ["offset" ] = self .normalize (pad .GetOffset ())
556+ try :
557+ pad_dict ["offset" ] = self .normalize (pad .GetOffset (layer ))
558+ except TypeError :
559+ pad_dict ["offset" ] = self .normalize (pad .GetOffset ())
511560 if self .config .include_nets :
512561 pad_dict ["net" ] = pad .GetNetname ()
513562
@@ -561,8 +610,7 @@ def parse_footprints(self):
561610 # footprint pads
562611 pads = []
563612 for p in f .Pads ():
564- pad_dict = self .parse_pad (p )
565- if pad_dict is not None :
613+ for pad_dict in self .parse_pad (p ):
566614 pads .append ((p .GetPadName (), pad_dict ))
567615
568616 if pads :
0 commit comments