pcbnew crash while opening old .brd file

Fixes: lp:1698697
https://bugs.launchpad.net/kicad/+bug/1698697

The incorrect method ZONE_CONTAINER::AppendCorner() is also fixed:
It was expecting the corner must be added to the main outline, but this is a false expectation:
it can be added to a hole inside the zone outline.
This commit is contained in:
jean-pierre charras 2017-06-19 13:29:57 +02:00
parent d6a56e5d3d
commit 6a63d4fbff
8 changed files with 69 additions and 35 deletions

View File

@ -2348,21 +2348,24 @@ void BOARD::RemoveArea( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_to
}
ZONE_CONTAINER* BOARD::InsertArea( int netcode, int iarea, PCB_LAYER_ID layer, int x, int y, int hatch )
ZONE_CONTAINER* BOARD::InsertArea( int aNetcode, int aAreaIdx, PCB_LAYER_ID aLayer,
int aCornerX, int aCornerY, int aHatch )
{
ZONE_CONTAINER* new_area = new ZONE_CONTAINER( this );
new_area->SetNetCode( netcode );
new_area->SetLayer( layer );
new_area->SetNetCode( aNetcode );
new_area->SetLayer( aLayer );
new_area->SetTimeStamp( GetNewTimeStamp() );
if( iarea < (int) ( m_ZoneDescriptorList.size() - 1 ) )
m_ZoneDescriptorList.insert( m_ZoneDescriptorList.begin() + iarea + 1, new_area );
if( aAreaIdx < (int) ( m_ZoneDescriptorList.size() - 1 ) )
m_ZoneDescriptorList.insert( m_ZoneDescriptorList.begin() + aAreaIdx + 1, new_area );
else
m_ZoneDescriptorList.push_back( new_area );
new_area->SetHatchStyle( (ZONE_CONTAINER::HATCH_STYLE) hatch );
new_area->AppendCorner( wxPoint( x, y ) );
new_area->SetHatchStyle( (ZONE_CONTAINER::HATCH_STYLE) aHatch );
// Add the first corner to the new zone
new_area->AppendCorner( wxPoint( aCornerX, aCornerY ), -1 );
return new_area;
}

View File

@ -1070,11 +1070,17 @@ public:
PCB_LAYER_ID aLayer, wxPoint aStartPointPosition, int aHatch );
/**
* Function InsertArea
* add empty copper area to net, inserting after m_ZoneDescriptorList[iarea]
* Add a copper area to net, inserting after m_ZoneDescriptorList[aAreaIdx]
* @param aNetcode is the netcode of the new copper zone
* @param aAreaIdx is the netcode of the new copper zone
* @param aLayer is the copper layer id of the new copper zone
* @param aCornerX,aCornerY is the coordinate of the first corner
* (a zone cannot have a empty outline)
* @param aHatch is the hatch option
* @return pointer to the new area
*/
ZONE_CONTAINER* InsertArea( int netcode, int iarea, PCB_LAYER_ID layer, int x, int y, int hatch );
ZONE_CONTAINER* InsertArea( int aNetcode, int aAreaIdx, PCB_LAYER_ID aLayer,
int aCornerX, int aCornerY, int aHatch );
/**
* Function NormalizeAreaPolygon

View File

@ -843,6 +843,24 @@ void ZONE_CONTAINER::AddPolygon( std::vector< wxPoint >& aPolygon )
}
bool ZONE_CONTAINER::AppendCorner( wxPoint aPosition, int aHoleIdx, bool aAllowDuplication )
{
// Ensure the main outline exists:
if( m_Poly->OutlineCount() == 0 )
m_Poly->NewOutline();
// If aHoleIdx >= 0, the corner musty be added to the hole, index aHoleIdx.
// (remember: the index of the first hole is 0)
// Return error if if does dot exist.
if( aHoleIdx >= m_Poly->HoleCount( 0 ) )
return false;
m_Poly->Append( aPosition.x, aPosition.y, -1, aHoleIdx, aAllowDuplication );
return true;
}
wxString ZONE_CONTAINER::GetSelectMenuText() const
{
wxString text;

View File

@ -537,18 +537,14 @@ public:
}
/**
* Function AppendCorner
* @param position is the position of the new corner.
* Add a new corner to the zone outline (to the main outline or a hole)
* @param aPosition is the position of the new corner.
* @param aHoleIdx is the index of the hole (-1 for the main outline, >= 0 for hole).
* @param aAllowDuplication is a flag to indicate whether it is allowed to add this corner
* even if it is duplicated.
* @return true if the corner was added, false if error (aHoleIdx > hole count -1)
*/
void AppendCorner( wxPoint position, bool aAllowDuplication = false )
{
if( m_Poly->OutlineCount() == 0 )
m_Poly->NewOutline();
m_Poly->Append( position.x, position.y, -1, -1, aAllowDuplication );
}
bool AppendCorner( wxPoint aPosition, int aHoleIdx, bool aAllowDuplication = false );
HATCH_STYLE GetHatchStyle() const
{

View File

@ -621,10 +621,11 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
ZONE_CONTAINER::HATCH_STYLE outline_hatch = ZONE_CONTAINER::DIAGONAL_EDGE;
zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y1 ) ) );
zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y1 ) ) );
zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y2 ) ) );
zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y2 ) ) );
const int outlineIdx = -1; // this is the id of the copper zone main outline
zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y1 ) ), outlineIdx );
zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y1 ) ), outlineIdx );
zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y2 ) ), outlineIdx );
zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y2 ) ), outlineIdx );
// this is not my fault:
zone->SetHatch( outline_hatch, Mils2iu( zone->GetDefaultHatchPitchMils() ), true );
@ -1812,7 +1813,7 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
EVERTEX v( vertex );
// Append the corner
zone->AppendCorner( wxPoint( kicad_x( v.x ), kicad_y( v.y ) ) );
zone->AppendCorner( wxPoint( kicad_x( v.x ), kicad_y( v.y ) ), -1 );
vertex = vertex->GetNext();
}

View File

@ -2475,7 +2475,8 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
unique_ptr<ZONE_CONTAINER> zc( new ZONE_CONTAINER( m_board ) );
ZONE_CONTAINER::HATCH_STYLE outline_hatch = ZONE_CONTAINER::NO_HATCH;
bool sawCorner = false;
bool endContour = false;
int holeIndex = -1; // -1 is the main outline; holeIndex >= 0 = hole index
char buf[1024];
char* line;
char* saveptr;
@ -2484,18 +2485,27 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
{
const char* data;
if( TESTLINE( "ZCorner" ) ) // new corner found
if( TESTLINE( "ZCorner" ) ) // new corner of the zone outlines found
{
// e.g. "ZCorner 25650 49500 0"
BIU x = biuParse( line + SZ( "ZCorner" ), &data );
BIU y = biuParse( data, &data );
if( !sawCorner )
if( endContour )
{
// the previous corner was the last corner of a contour.
// so this corner is the first of a new hole
endContour = false;
zc->NewHole();
else
zc->AppendCorner( wxPoint( x, y ) );
holeIndex++;
}
sawCorner = true;
zc->AppendCorner( wxPoint( x, y ), holeIndex );
// Is this corner the end of current contour?
// the next corner (if any) will be stored in a new contour (a hole)
// intParse( data )returns 0 = usual corner, 1 = last corner of the current contour:
endContour = intParse( data );
}
else if( TESTLINE( "ZInfo" ) ) // general info found
@ -2655,7 +2665,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
else if( TESTLINE( "$POLYSCORNERS" ) )
{
// Read the PolysList (polygons used for fill areas in the zone)
// Read the PolysList (polygons that are the solid areas in the filled zone)
SHAPE_POLY_SET polysList;
bool makeNewOutline = true;

View File

@ -182,7 +182,7 @@ void PCB_POLYGON::AddToBoard()
for( i = 0; i < (int) m_outline.GetCount(); i++ )
{
zone->AppendCorner( wxPoint( KiROUND( m_outline[i]->x ),
KiROUND( m_outline[i]->y ) ) );
KiROUND( m_outline[i]->y ) ), -1 );
}
zone->SetZoneClearance( m_width );
@ -206,7 +206,6 @@ void PCB_POLYGON::AddToBoard()
}
//if( m_filled )
// cvpcb is not linked
// zone->BuildFilledPolysListData( m_board );
}
}

View File

@ -669,8 +669,9 @@ int PCB_EDIT_FRAME::Begin_Zone( wxDC* DC )
zone->SetLayer( zoneInfo.m_CurrentZone_Layer );
// A duplicated corner is needed; null segments are removed when the zone is finished.
zone->AppendCorner( GetCrossHairPosition() );
zone->AppendCorner( GetCrossHairPosition(), true );
zone->AppendCorner( GetCrossHairPosition(), -1 );
// Add the duplicate corner:
zone->AppendCorner( GetCrossHairPosition(), -1, true );
if( g_Drc_On && (m_drc->Drc( zone, 0 ) == BAD_DRC) && zone->IsOnCopperLayer() )
{