Force removal of zero-sized pads on load.

Pads with zero width or height cause issues when rendering and
selecting.  KiCad has never allowed these elements but hasn't prevented
importing systems where they exist.  This prevents their import and
cleans existing designs where the pads are placed

Fixes https://gitlab.com/kicad/code/kicad/issues/12200

(cherry picked from commit 2ee65b2d83)
This commit is contained in:
Seth Hillbrand 2022-08-13 18:51:14 -07:00
parent 83eb9e03b1
commit 29cadaf54e
6 changed files with 58 additions and 26 deletions

View File

@ -43,6 +43,7 @@
#include <convert_basic_shapes_to_polygon.h> #include <convert_basic_shapes_to_polygon.h>
#include <trigo.h> #include <trigo.h>
#include <macros.h> #include <macros.h>
#include <wx/debug.h>
#include <wx/log.h> #include <wx/log.h>
#include <limits> // std::numeric_limits #include <limits> // std::numeric_limits
@ -801,7 +802,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadLibraryCoppers( const SYMDEF_PCB& aComponen
if( !found ) if( !found )
anchorPad = aComponent.ComponentPads.at( compCopper.AssociatedPadIDs.front() ); anchorPad = aComponent.ComponentPads.at( compCopper.AssociatedPadIDs.front() );
PAD* pad = new PAD( aFootprint ); std::unique_ptr<PAD> pad = std::make_unique<PAD>( aFootprint );
pad->SetAttribute( PAD_ATTRIB::SMD ); pad->SetAttribute( PAD_ATTRIB::SMD );
pad->SetLayerSet( LSET( 1, copperLayer ) ); pad->SetLayerSet( LSET( 1, copperLayer ) );
pad->SetNumber( anchorPad.Identifier.IsEmpty() pad->SetNumber( anchorPad.Identifier.IsEmpty()
@ -815,6 +816,9 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadLibraryCoppers( const SYMDEF_PCB& aComponen
int anchorSize = getKiCadLength( anchorpadcode.Shape.Size ); int anchorSize = getKiCadLength( anchorpadcode.Shape.Size );
wxPoint anchorPos = getKiCadPoint( anchorPad.Position ); wxPoint anchorPos = getKiCadPoint( anchorPad.Position );
if( anchorSize <= 0 )
anchorSize = 1;
pad->SetShape( PAD_SHAPE::CUSTOM ); pad->SetShape( PAD_SHAPE::CUSTOM );
pad->SetAnchorPadShape( PAD_SHAPE::CIRCLE ); pad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
pad->SetSize( { anchorSize, anchorSize } ); pad->SetSize( { anchorSize, anchorSize } );
@ -828,7 +832,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadLibraryCoppers( const SYMDEF_PCB& aComponen
shapePolys.Move( aFootprint->GetPosition() - anchorPos ); shapePolys.Move( aFootprint->GetPosition() - anchorPos );
pad->AddPrimitivePoly( shapePolys, 0, true ); pad->AddPrimitivePoly( shapePolys, 0, true );
aFootprint->Add( pad, ADD_MODE::APPEND ); // Append so that we get the correct behaviour aFootprint->Add( pad.release(), ADD_MODE::APPEND ); // Append so that we get the correct behaviour
// when finding pads by PAD_ID. See loadNets() // when finding pads by PAD_ID. See loadNets()
m_librarycopperpads[aComponent.ID][anchorPad.ID].push_back( aFootprint->Pads().size() ); m_librarycopperpads[aComponent.ID][anchorPad.ID].push_back( aFootprint->Pads().size() );
@ -905,9 +909,9 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadLibraryPads( const SYMDEF_PCB& aComponent,
{ {
for( std::pair<PAD_ID, COMPONENT_PAD> padPair : aComponent.ComponentPads ) for( std::pair<PAD_ID, COMPONENT_PAD> padPair : aComponent.ComponentPads )
{ {
PAD* pad = getKiCadPad( padPair.second, aFootprint ); if( PAD* pad = getKiCadPad( padPair.second, aFootprint ) )
aFootprint->Add( pad, ADD_MODE::APPEND ); // Append so that we get correct behaviour aFootprint->Add( pad, ADD_MODE::APPEND ); // Append so that we get correct behaviour
// when finding pads by PAD_ID - see loadNets() // when finding pads by PAD_ID - see loadNets()
} }
} }
@ -917,7 +921,10 @@ PAD* CADSTAR_PCB_ARCHIVE_LOADER::getKiCadPad( const COMPONENT_PAD& aCadstarPad,
PADCODE csPadcode = getPadCode( aCadstarPad.PadCodeID ); PADCODE csPadcode = getPadCode( aCadstarPad.PadCodeID );
wxString errorMSG; wxString errorMSG;
PAD* pad = new PAD( aParent ); if( csPadcode.Shape.Size <= 0)
return nullptr;
std::unique_ptr<PAD> pad = std::make_unique<PAD>( aParent );
LSET padLayerSet; LSET padLayerSet;
switch( aCadstarPad.Side ) switch( aCadstarPad.Side )
@ -1238,7 +1245,7 @@ PAD* CADSTAR_PCB_ARCHIVE_LOADER::getKiCadPad( const COMPONENT_PAD& aCadstarPad,
m_padcodesTested.insert( csPadcode.ID ); m_padcodesTested.insert( csPadcode.ID );
} }
return pad; return pad.release();
} }
@ -1713,11 +1720,14 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadComponents()
wxString padNumber = kiPad->GetNumber(); wxString padNumber = kiPad->GetNumber();
delete kiPad; delete kiPad;
kiPad = getKiCadPad( csPad, footprint );
kiPad->SetNumber( padNumber );
// Change the pointer in the footprint to the newly created pad if( kiPad = getKiCadPad( csPad, footprint ) )
getPadReference( footprint, padEx.ID ) = kiPad; {
kiPad->SetNumber( padNumber );
// Change the pointer in the footprint to the newly created pad
getPadReference( footprint, padEx.ID ) = kiPad;
}
} }
} }

View File

@ -1892,9 +1892,8 @@ void EAGLE_PLUGIN::packagePad( FOOTPRINT* aFootprint, wxXmlNode* aTree )
int shape = EPAD::UNDEF; int shape = EPAD::UNDEF;
int eagleDrillz = e.drill.ToPcbUnits(); int eagleDrillz = e.drill.ToPcbUnits();
PAD* pad = new PAD( aFootprint ); std::unique_ptr<PAD> pad = std::make_unique<PAD>( aFootprint );
aFootprint->Add( pad ); transferPad( e, pad.get() );
transferPad( e, pad );
if( e.first && *e.first && m_rules->psFirst != EPAD::UNDEF ) if( e.first && *e.first && m_rules->psFirst != EPAD::UNDEF )
shape = m_rules->psFirst; shape = m_rules->psFirst;
@ -1980,6 +1979,11 @@ void EAGLE_PLUGIN::packagePad( FOOTPRINT* aFootprint, wxXmlNode* aTree )
{ {
pad->SetOrientation( e.rot->degrees * 10 ); pad->SetOrientation( e.rot->degrees * 10 );
} }
if( pad->GetSizeX() > 0 && pad->GetSizeY() > 0 )
{
aFootprint->Add( pad.release() );
}
} }

View File

@ -2238,7 +2238,7 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
auto net_it = netinfo.find( netname ); auto net_it = netinfo.find( netname );
PAD* newpad = new PAD( fp ); std::unique_ptr<PAD> newpad = std::make_unique<PAD>( fp );
if( net_it != netinfo.end() ) if( net_it != netinfo.end() )
newpad->SetNet( net_it->second ); newpad->SetNet( net_it->second );
@ -2256,8 +2256,8 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
if( padstack == pads.end() ) if( padstack == pads.end() )
{ {
///TODO:Warning wxLogError( _( "Unable to locate padstack %s in file %s\n" ),
delete newpad; pin->padstack.c_str(), aBoard->GetFileName().wc_str() );
continue; continue;
} }
else else
@ -2409,7 +2409,10 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
else else
newpad->SetOrientation( ( src->rotate - pin->rotation ) * 10.0 ); newpad->SetOrientation( ( src->rotate - pin->rotation ) * 10.0 );
fp->Add( newpad, ADD_MODE::APPEND ); if( newpad->GetSizeX() > 0 || newpad->GetSizeY() > 0 )
{
fp->Add( newpad.release(), ADD_MODE::APPEND );
}
} }
} }

View File

@ -536,7 +536,7 @@ FOOTPRINT* GPCB_FPL_CACHE::parseFOOTPRINT( LINE_READER* aLineReader )
aLineReader->LineNumber(), 0 ); aLineReader->LineNumber(), 0 );
} }
PAD* pad = new PAD( footprint.get() ); std::unique_ptr<PAD> pad = std::make_unique<PAD>( footprint.get() );
static const LSET pad_front( 3, F_Cu, F_Mask, F_Paste ); static const LSET pad_front( 3, F_Cu, F_Mask, F_Paste );
static const LSET pad_back( 3, B_Cu, B_Mask, B_Paste ); static const LSET pad_back( 3, B_Cu, B_Mask, B_Paste );
@ -604,7 +604,11 @@ FOOTPRINT* GPCB_FPL_CACHE::parseFOOTPRINT( LINE_READER* aLineReader )
pad->SetShape( PAD_SHAPE::OVAL ); pad->SetShape( PAD_SHAPE::OVAL );
} }
footprint->Add( pad ); if( pad->GetSizeX() > 0 && pad->GetSizeY() > 0 )
{
footprint->Add( pad.release() );
}
continue; continue;
} }

View File

@ -3479,12 +3479,14 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments
case T_pad: case T_pad:
{ {
PAD* pad = parsePAD( footprint.get() ); if( PAD* pad = parsePAD( footprint.get() ) )
pt = pad->GetPos0(); {
pt = pad->GetPos0();
RotatePoint( &pt, footprint->GetOrientation() );
pad->SetPosition( pt + footprint->GetPosition() );
footprint->Add( pad, ADD_MODE::APPEND );
}
RotatePoint( &pt, footprint->GetOrientation() );
pad->SetPosition( pt + footprint->GetPosition() );
footprint->Add( pad, ADD_MODE::APPEND );
break; break;
} }
@ -4498,6 +4500,11 @@ PAD* PCB_PARSER::parsePAD( FOOTPRINT* aParent )
if( !pad->GetRemoveUnconnected() ) if( !pad->GetRemoveUnconnected() )
pad->SetKeepTopBottom( true ); pad->SetKeepTopBottom( true );
// Zero-sized pads are not really selectable and likely cause crashes.
// They are not supported by KiCad and are removed on loading
if( pad->GetSizeX() <= 0 || pad->GetSizeY() <= 0 )
return nullptr;
return pad.release(); return pad.release();
} }

View File

@ -1543,7 +1543,11 @@ void LEGACY_PLUGIN::loadPAD( FOOTPRINT* aFootprint )
pad->SetPosition( padpos + aFootprint->GetPosition() ); pad->SetPosition( padpos + aFootprint->GetPosition() );
aFootprint->Add( pad.release() ); if( pad->GetSizeX() > 0 && pad->GetSizeY() > 0 )
{
aFootprint->Add( pad.release() );
}
return; // preferred exit return; // preferred exit
} }
} }