Gerbview: try to fix a crash (hard to reproduce) which someting happens when closing gerbview. Fix incorrect calculation of bounding boxes.

This commit is contained in:
jean-pierre charras 2016-06-15 10:26:41 +02:00
parent 7ff3dd0807
commit 947c73f23b
10 changed files with 60 additions and 82 deletions

View File

@ -59,6 +59,7 @@ bool GBR_LAYOUT::IsLayerPrintable( int aLayer ) const
EDA_RECT GBR_LAYOUT::ComputeBoundingBox() EDA_RECT GBR_LAYOUT::ComputeBoundingBox()
{ {
EDA_RECT bbox; EDA_RECT bbox;
bool first_item = true;
for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer ) for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
{ {
@ -68,7 +69,15 @@ EDA_RECT GBR_LAYOUT::ComputeBoundingBox()
continue; continue;
for( GERBER_DRAW_ITEM* item = gerber->GetItemsList(); item; item = item->Next() ) for( GERBER_DRAW_ITEM* item = gerber->GetItemsList(); item; item = item->Next() )
bbox.Merge( item->GetBoundingBox() ); {
if( first_item )
{
bbox = item->GetBoundingBox();
first_item = false;
}
else
bbox.Merge( item->GetBoundingBox() );
}
} }
SetBoundingBox( bbox ); SetBoundingBox( bbox );

View File

@ -207,8 +207,15 @@ const EDA_RECT GERBER_DRAW_ITEM::GetBoundingBox() const
bbox.Inflate( m_Size.x / 2, m_Size.y / 2 ); bbox.Inflate( m_Size.x / 2, m_Size.y / 2 );
bbox.SetOrigin( GetABPosition( bbox.GetOrigin() ) ); // calculate the corners coordinates in current gerber axis orientations
bbox.SetEnd( GetABPosition( bbox.GetEnd() ) ); wxPoint org = GetABPosition( bbox.GetOrigin() );
wxPoint end = GetABPosition( bbox.GetEnd() );
// Set the corners position:
bbox.SetOrigin( org );
bbox.SetEnd( end );
bbox.Normalize();
return bbox; return bbox;
} }

View File

@ -107,6 +107,8 @@ GERBER_FILE_IMAGE::GERBER_FILE_IMAGE( int aLayer )
GERBER_FILE_IMAGE::~GERBER_FILE_IMAGE() GERBER_FILE_IMAGE::~GERBER_FILE_IMAGE()
{ {
m_Drawings.DeleteAll();
for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ ) for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ )
{ {
delete m_Aperture_List[ii]; delete m_Aperture_List[ii];

View File

@ -47,17 +47,13 @@ GERBER_FILE_IMAGE_LIST::GERBER_FILE_IMAGE_LIST()
m_GERBER_List.push_back( NULL ); m_GERBER_List.push_back( NULL );
} }
GERBER_FILE_IMAGE_LIST::~GERBER_FILE_IMAGE_LIST() GERBER_FILE_IMAGE_LIST::~GERBER_FILE_IMAGE_LIST()
{ {
ClearList(); DeleteAllImages();
for( unsigned layer = 0; layer < m_GERBER_List.size(); ++layer )
{
delete m_GERBER_List[layer];
m_GERBER_List[layer] = NULL;
}
} }
GERBER_FILE_IMAGE* GERBER_FILE_IMAGE_LIST::GetGbrImage( int aIdx ) GERBER_FILE_IMAGE* GERBER_FILE_IMAGE_LIST::GetGbrImage( int aIdx )
{ {
if( (unsigned)aIdx < m_GERBER_List.size() ) if( (unsigned)aIdx < m_GERBER_List.size() )
@ -66,11 +62,10 @@ GERBER_FILE_IMAGE* GERBER_FILE_IMAGE_LIST::GetGbrImage( int aIdx )
return NULL; return NULL;
} }
/** /* creates a new, empty GERBER_FILE_IMAGE* at index aIdx
* creates a new, empty GERBER_FILE_IMAGE* at index aIdx
* or at the first free location if aIdx < 0 * or at the first free location if aIdx < 0
* @param aIdx = the location to use ( 0 ... GERBER_DRAWLAYERS_COUNT-1 ) * aIdx = the index of graphic layer to use, or -1 to uses the first free graphic layer
* @return true if the index used, or -1 if no room to add image * return the index actually used, or -1 if no room to add image
*/ */
int GERBER_FILE_IMAGE_LIST::AddGbrImage( GERBER_FILE_IMAGE* aGbrImage, int aIdx ) int GERBER_FILE_IMAGE_LIST::AddGbrImage( GERBER_FILE_IMAGE* aGbrImage, int aIdx )
{ {
@ -80,7 +75,7 @@ int GERBER_FILE_IMAGE_LIST::AddGbrImage( GERBER_FILE_IMAGE* aGbrImage, int aIdx
{ {
for( idx = 0; idx < (int)m_GERBER_List.size(); idx++ ) for( idx = 0; idx < (int)m_GERBER_List.size(); idx++ )
{ {
if( !IsUsed( idx ) ) if( m_GERBER_List[idx] == NULL )
break; break;
} }
} }
@ -94,23 +89,24 @@ int GERBER_FILE_IMAGE_LIST::AddGbrImage( GERBER_FILE_IMAGE* aGbrImage, int aIdx
} }
// remove all loaded data in list, but do not delete empty images void GERBER_FILE_IMAGE_LIST::DeleteAllImages()
// (can be reused)
void GERBER_FILE_IMAGE_LIST::ClearList()
{ {
for( unsigned layer = 0; layer < m_GERBER_List.size(); ++layer ) for( unsigned idx = 0; idx < m_GERBER_List.size(); ++idx )
ClearImage( layer ); DeleteImage( idx );
} }
// remove the loaded data of image aIdx, but do not delete it
void GERBER_FILE_IMAGE_LIST::ClearImage( int aIdx ) void GERBER_FILE_IMAGE_LIST::DeleteImage( int aIdx )
{ {
if( aIdx >= 0 && aIdx < (int)m_GERBER_List.size() && m_GERBER_List[aIdx] ) // Ensure the index is valid:
{ if( aIdx < 0 || aIdx >= int( m_GERBER_List.size() ) )
m_GERBER_List[aIdx]->InitToolTable(); return;
m_GERBER_List[aIdx]->ResetDefaultValues();
m_GERBER_List[aIdx]->m_InUse = false; // delete image aIdx
} GERBER_FILE_IMAGE* gbr_image = GetGbrImage( aIdx );
delete gbr_image;
m_GERBER_List[ aIdx ] = NULL;
} }
// Build a name for image aIdx which can be used in layers manager // Build a name for image aIdx which can be used in layers manager
@ -127,7 +123,7 @@ const wxString GERBER_FILE_IMAGE_LIST::GetDisplayName( int aIdx )
// <id> <short filename> <X2 FileFunction info> if a X2 FileFunction info is found // <id> <short filename> <X2 FileFunction info> if a X2 FileFunction info is found
// or (if no FileFunction info) // or (if no FileFunction info)
// <id> <short filename> * // <id> <short filename> *
if( gerber && IsUsed(aIdx ) ) if( gerber )
{ {
wxFileName fn( gerber->m_FileName ); wxFileName fn( gerber->m_FileName );
wxString filename = fn.GetFullName(); wxString filename = fn.GetFullName();
@ -168,14 +164,7 @@ const wxString GERBER_FILE_IMAGE_LIST::GetDisplayName( int aIdx )
return name; return name;
} }
// return true if image is used (loaded and not cleared)
bool GERBER_FILE_IMAGE_LIST::IsUsed( int aIdx )
{
if( aIdx >= 0 && aIdx < (int)m_GERBER_List.size() )
return m_GERBER_List[aIdx] != NULL && m_GERBER_List[aIdx]->m_InUse;
return false;
}
// Helper function, for std::sort. // Helper function, for std::sort.
// Sort loaded images by Z order priority, if they have the X2 FileFormat info // Sort loaded images by Z order priority, if they have the X2 FileFormat info

View File

@ -28,7 +28,6 @@
#include <vector> #include <vector>
#include <set> #include <set>
//#include <dcode.h>
#include <class_gerber_draw_item.h> #include <class_gerber_draw_item.h>
#include <class_aperture_macro.h> #include <class_aperture_macro.h>
@ -83,15 +82,15 @@ public:
/** /**
* remove all loaded data in list * remove all loaded data in list, and delete all images. Memory is freed
*/ */
void ClearList(); void DeleteAllImages();
/** /**
* remove the loaded data of image aIdx * delete the loaded data of image aIdx. Memory is freed
* @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 ) * @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 )
*/ */
void ClearImage( int aIdx ); void DeleteImage( int aIdx );
/** /**
* @return a name for image aIdx which can be used in layers manager * @return a name for image aIdx which can be used in layers manager
@ -106,12 +105,6 @@ public:
*/ */
const wxString GetDisplayName( int aIdx ); const wxString GetDisplayName( int aIdx );
/**
* @return true if image is used (loaded and with items)
* @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 )
*/
bool IsUsed( int aIdx );
/** /**
* Sort loaded images by Z order priority, if they have the X2 FileFormat info * Sort loaded images by Z order priority, if they have the X2 FileFormat info
* (SortImagesByZOrder updates the graphic layer of these items) * (SortImagesByZOrder updates the graphic layer of these items)

View File

@ -307,11 +307,11 @@ void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
/* /*
* Virtual Function useAlternateBitmap * Virtual Function useAlternateBitmap
* return true if bitmaps shown in Render layer list * return true if bitmaps shown in Render layer list
* must be alternate bitmaps, or false to use "normal" bitmaps * must be alternate bitmap (when a gerber iùmage is loaded), or false to use "normal" bitmap
*/ */
bool GERBER_LAYER_WIDGET::useAlternateBitmap(int aRow) bool GERBER_LAYER_WIDGET::useAlternateBitmap(int aRow)
{ {
return g_GERBER_List.IsUsed( aRow ); return g_GERBER_List.GetGbrImage( aRow ) != NULL;
} }
/* /*

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -47,22 +47,10 @@ bool GERBVIEW_FRAME::Clear_DrawLayers( bool query )
return false; return false;
} }
for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer ) g_GERBER_List.DeleteAllImages();
{
GERBER_FILE_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer );
if( gerber == NULL ) // Graphic layer not yet used
continue;
gerber->m_Drawings.DeleteAll();
}
g_GERBER_List.ClearList();
GetGerberLayout()->SetBoundingBox( EDA_RECT() ); GetGerberLayout()->SetBoundingBox( EDA_RECT() );
SetScreen( new GBR_SCREEN( GetPageSettings().GetSizeIU() ) );
setActiveLayer( 0 ); setActiveLayer( 0 );
m_LayersManager->UpdateLayerIcons(); m_LayersManager->UpdateLayerIcons();
syncLayerBox(); syncLayerBox();
@ -82,15 +70,9 @@ void GERBVIEW_FRAME::Erase_Current_DrawLayer( bool query )
SetCurItem( NULL ); SetCurItem( NULL );
GERBER_FILE_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer ); g_GERBER_List.DeleteImage( layer );
if( gerber ) // gerber == NULL should not occur
gerber->m_Drawings.DeleteAll();
g_GERBER_List.ClearImage( layer );
GetScreen()->SetModify();
m_canvas->Refresh();
m_LayersManager->UpdateLayerIcons(); m_LayersManager->UpdateLayerIcons();
syncLayerBox(); syncLayerBox();
m_canvas->Refresh();
} }

View File

@ -144,8 +144,4 @@ void GERBVIEW_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg )
m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
m_canvas->DrawCrossHair( DC ); m_canvas->DrawCrossHair( DC );
// Display the filename and the layer name (found in the gerber files, if any)
// relative to the active layer
UpdateTitleAndInfo();
} }

View File

@ -247,11 +247,11 @@ double GERBVIEW_FRAME::BestZoom()
bbox.SetSize( wxSize( Mils2iu( pagesize.x ), Mils2iu( pagesize.y ) ) ); bbox.SetSize( wxSize( Mils2iu( pagesize.x ), Mils2iu( pagesize.y ) ) );
} }
// Compute best zoom:
wxSize size = m_canvas->GetClientSize(); wxSize size = m_canvas->GetClientSize();
double x = (double) bbox.GetWidth() / (double) size.x;
double x = (double) bbox.GetWidth() * 1.1 / (double) size.x; double y = (double) bbox.GetHeight() / (double) size.y;
double y = (double) bbox.GetHeight() * 1.1 / (double) size.y; double best_zoom = std::max( x, y ) * 1.1;
double best_zoom = std::max( x, y );
SetScrollCenterPosition( bbox.Centre() ); SetScrollCenterPosition( bbox.Centre() );
@ -373,10 +373,10 @@ int GERBVIEW_FRAME::getNextAvailableLayer( int aLayer ) const
{ {
GERBER_FILE_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer ); GERBER_FILE_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer );
if( gerber == NULL || gerber->m_FileName.IsEmpty() ) if( gerber == NULL ) // this graphic layer is available: use it
return layer; return layer;
++layer; ++layer; // try next graphic layer
if( layer >= GERBER_DRAWLAYERS_COUNT ) if( layer >= GERBER_DRAWLAYERS_COUNT )
layer = 0; layer = 0;

View File

@ -319,7 +319,7 @@ void GERBVIEW_FRAME::OnUpdateSelectDCode( wxUpdateUIEvent& aEvent )
void GERBVIEW_FRAME::OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent ) void GERBVIEW_FRAME::OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent )
{ {
if( m_SelLayerBox && (m_SelLayerBox->GetSelection() != getActiveLayer()) ) if( m_SelLayerBox->GetSelection() != getActiveLayer() )
{ {
m_SelLayerBox->SetSelection( getActiveLayer() ); m_SelLayerBox->SetSelection( getActiveLayer() );
} }