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 ); ZONE_CONTAINER* new_area = new ZONE_CONTAINER( this );
new_area->SetNetCode( netcode ); new_area->SetNetCode( aNetcode );
new_area->SetLayer( layer ); new_area->SetLayer( aLayer );
new_area->SetTimeStamp( GetNewTimeStamp() ); new_area->SetTimeStamp( GetNewTimeStamp() );
if( iarea < (int) ( m_ZoneDescriptorList.size() - 1 ) ) if( aAreaIdx < (int) ( m_ZoneDescriptorList.size() - 1 ) )
m_ZoneDescriptorList.insert( m_ZoneDescriptorList.begin() + iarea + 1, new_area ); m_ZoneDescriptorList.insert( m_ZoneDescriptorList.begin() + aAreaIdx + 1, new_area );
else else
m_ZoneDescriptorList.push_back( new_area ); m_ZoneDescriptorList.push_back( new_area );
new_area->SetHatchStyle( (ZONE_CONTAINER::HATCH_STYLE) hatch ); new_area->SetHatchStyle( (ZONE_CONTAINER::HATCH_STYLE) aHatch );
new_area->AppendCorner( wxPoint( x, y ) );
// Add the first corner to the new zone
new_area->AppendCorner( wxPoint( aCornerX, aCornerY ), -1 );
return new_area; return new_area;
} }

View File

@ -1070,11 +1070,17 @@ public:
PCB_LAYER_ID aLayer, wxPoint aStartPointPosition, int aHatch ); PCB_LAYER_ID aLayer, wxPoint aStartPointPosition, int aHatch );
/** /**
* Function InsertArea * Add a copper area to net, inserting after m_ZoneDescriptorList[aAreaIdx]
* add empty copper area to net, inserting after m_ZoneDescriptorList[iarea] * @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 * @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 * 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 ZONE_CONTAINER::GetSelectMenuText() const
{ {
wxString text; wxString text;

View File

@ -537,18 +537,14 @@ public:
} }
/** /**
* Function AppendCorner * Add a new corner to the zone outline (to the main outline or a hole)
* @param position is the position of the new corner. * @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 * @param aAllowDuplication is a flag to indicate whether it is allowed to add this corner
* even if it is duplicated. * 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 ) bool AppendCorner( wxPoint aPosition, int aHoleIdx, bool aAllowDuplication = false );
{
if( m_Poly->OutlineCount() == 0 )
m_Poly->NewOutline();
m_Poly->Append( position.x, position.y, -1, -1, aAllowDuplication );
}
HATCH_STYLE GetHatchStyle() const 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_CONTAINER::HATCH_STYLE outline_hatch = ZONE_CONTAINER::DIAGONAL_EDGE;
zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y1 ) ) ); const int outlineIdx = -1; // this is the id of the copper zone main outline
zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y1 ) ) ); zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y1 ) ), outlineIdx );
zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y2 ) ) ); zone->AppendCorner( wxPoint( kicad_x( r.x2 ), kicad_y( r.y1 ) ), outlineIdx );
zone->AppendCorner( wxPoint( kicad_x( r.x1 ), kicad_y( r.y2 ) ) ); 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: // this is not my fault:
zone->SetHatch( outline_hatch, Mils2iu( zone->GetDefaultHatchPitchMils() ), true ); zone->SetHatch( outline_hatch, Mils2iu( zone->GetDefaultHatchPitchMils() ), true );
@ -1812,7 +1813,7 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
EVERTEX v( vertex ); EVERTEX v( vertex );
// Append the corner // 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(); vertex = vertex->GetNext();
} }

View File

@ -2475,7 +2475,8 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
unique_ptr<ZONE_CONTAINER> zc( new ZONE_CONTAINER( m_board ) ); unique_ptr<ZONE_CONTAINER> zc( new ZONE_CONTAINER( m_board ) );
ZONE_CONTAINER::HATCH_STYLE outline_hatch = ZONE_CONTAINER::NO_HATCH; 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 buf[1024];
char* line; char* line;
char* saveptr; char* saveptr;
@ -2484,18 +2485,27 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
{ {
const char* data; 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" // e.g. "ZCorner 25650 49500 0"
BIU x = biuParse( line + SZ( "ZCorner" ), &data ); BIU x = biuParse( line + SZ( "ZCorner" ), &data );
BIU y = biuParse( data, &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(); zc->NewHole();
else holeIndex++;
zc->AppendCorner( wxPoint( x, y ) ); }
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 else if( TESTLINE( "ZInfo" ) ) // general info found
@ -2655,7 +2665,7 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER()
else if( TESTLINE( "$POLYSCORNERS" ) ) 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; SHAPE_POLY_SET polysList;
bool makeNewOutline = true; bool makeNewOutline = true;

View File

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

View File

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