From 961b22d6032f67cad58a1ae1be7654c06de71de3 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Thu, 30 May 2019 06:33:59 -0700 Subject: [PATCH] pcbnew: Changing drawings from dlist to std::deque --- common/base_struct.cpp | 17 +----- common/swig/kicad.i | 1 + include/base_struct.h | 60 ++++++++++++++----- include/macros.h | 3 + ...board_items_to_polygon_shape_transform.cpp | 2 +- pcbnew/class_board.cpp | 13 ++-- pcbnew/class_board.h | 15 ++--- pcbnew/kicad_plugin.cpp | 4 +- pcbnew/pcb_legacy_draw_utils.cpp | 2 +- pcbnew/swig/pcbnew_action_plugins.cpp | 4 +- pcbnew/tools/pcbnew_control.cpp | 19 +++++- qa/pcbnew/CMakeLists.txt | 1 + 12 files changed, 93 insertions(+), 48 deletions(-) diff --git a/common/base_struct.cpp b/common/base_struct.cpp index f062438031..988f086f99 100644 --- a/common/base_struct.cpp +++ b/common/base_struct.cpp @@ -26,6 +26,8 @@ * @brief Implementation of EDA_ITEM base class for KiCad. */ +#include + #include #include #include @@ -127,21 +129,6 @@ EDA_ITEM* EDA_ITEM::Clone() const } -SEARCH_RESULT EDA_ITEM::IterateForward( EDA_ITEM* listStart, - INSPECTOR inspector, - void* testData, - const KICAD_T scanTypes[] ) -{ - for( EDA_ITEM* p = listStart; p; p = p->Pnext ) - { - if( SEARCH_QUIT == p->Visit( inspector, testData, scanTypes ) ) - return SEARCH_QUIT; - } - - return SEARCH_CONTINUE; -} - - // see base_struct.h // many classes inherit this method, be careful: SEARCH_RESULT EDA_ITEM::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ) diff --git a/common/swig/kicad.i b/common/swig/kicad.i index d21f65359b..30e9439613 100644 --- a/common/swig/kicad.i +++ b/common/swig/kicad.i @@ -27,6 +27,7 @@ * @brief General wrappers for kicad / wx structures and classes */ +%include %include %include %include diff --git a/include/base_struct.h b/include/base_struct.h index 00fb5e9018..5ea1383dbe 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -32,6 +32,8 @@ #ifndef BASE_STRUCT_H_ #define BASE_STRUCT_H_ +#include + #include #include "common.h" @@ -366,6 +368,22 @@ public: */ virtual EDA_ITEM* Clone() const; // should not be inline, to save the ~ 6 bytes per call site. + /** + * Function Visit + * may be re-implemented for each derived class in order to handle + * all the types given by its member data. Implementations should call + * inspector->Inspect() on types in scanTypes[], and may use + * IterateForward() + * to do so on lists of such data. + * @param inspector An INSPECTOR instance to use in the inspection. + * @param testData Arbitrary data used by the inspector. + * @param scanTypes Which KICAD_T types are of interest and the order + * is significant too, terminated by EOT. + * @return SEARCH_RESULT SEARCH_QUIT if the Iterator is to stop the scan, + * else SCAN_CONTINUE, and determined by the inspector. + */ + virtual SEARCH_RESULT Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ); + /** * Function IterateForward * walks through the object tree calling the inspector() on each object @@ -386,23 +404,37 @@ public: static SEARCH_RESULT IterateForward( EDA_ITEM* listStart, INSPECTOR inspector, void* testData, - const KICAD_T scanTypes[] ); + const KICAD_T scanTypes[] ) + + { + for( EDA_ITEM* p = listStart; p; p = p->Pnext ) + { + if( SEARCH_QUIT == p->Visit( inspector, testData, scanTypes ) ) + return SEARCH_QUIT; + } + + return SEARCH_CONTINUE; + } /** - * Function Visit - * may be re-implemented for each derived class in order to handle - * all the types given by its member data. Implementations should call - * inspector->Inspect() on types in scanTypes[], and may use - * IterateForward() - * to do so on lists of such data. - * @param inspector An INSPECTOR instance to use in the inspection. - * @param testData Arbitrary data used by the inspector. - * @param scanTypes Which KICAD_T types are of interest and the order - * is significant too, terminated by EOT. - * @return SEARCH_RESULT SEARCH_QUIT if the Iterator is to stop the scan, - * else SCAN_CONTINUE, and determined by the inspector. + * @copydoc SEARCH_RESULT IterateForward( EDA_ITEM*, INSPECTOR, void*, const KICAD_T ) + * + * This changes first parameter to avoid the DList and use the main queue instead */ - virtual SEARCH_RESULT Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ); + template< class T > + static SEARCH_RESULT IterateForward( std::deque& aList, + INSPECTOR inspector, + void* testData, + const KICAD_T scanTypes[] ) + { + for( auto it : aList ) + { + if( static_cast( it )->Visit( inspector, testData, scanTypes ) == SEARCH_QUIT ) + return SEARCH_QUIT; + } + + return SEARCH_CONTINUE; + } /** * Function GetClass diff --git a/include/macros.h b/include/macros.h index 7f75281f1f..080b7cdf46 100644 --- a/include/macros.h +++ b/include/macros.h @@ -31,6 +31,7 @@ #define MACROS_H #include +#include #include #include #include @@ -149,12 +150,14 @@ template inline const T& Clamp( const T& lower, const T& value, con #ifdef SWIG /// Declare a std::vector and also the swig %template in unison #define DECL_VEC_FOR_SWIG(TypeName, MemberType) namespace std { %template(TypeName) vector; } typedef std::vector TypeName; +#define DECL_DEQ_FOR_SWIG(TypeName, MemberType) namespace std { %template(TypeName) deque; } typedef std::deque TypeName; #define DECL_MAP_FOR_SWIG(TypeName, KeyType, ValueType) namespace std { %template(TypeName) map; } typedef std::map TypeName; #define DECL_SPTR_FOR_SWIG(TypeName, MemberType) %shared_ptr(MemberType) namespace std { %template(TypeName) shared_ptr; } typedef std::shared_ptr TypeName; #define DECL_SET_FOR_SWIG(TypeName, MemberType) namespace std { %template(TypeName) set; } typedef std::set TypeName; #else /// Declare a std::vector but no swig %template #define DECL_VEC_FOR_SWIG(TypeName, MemberType) typedef std::vector TypeName; +#define DECL_DEQ_FOR_SWIG(TypeName, MemberType) typedef std::deque TypeName; #define DECL_MAP_FOR_SWIG(TypeName, KeyType, ValueType) typedef std::map TypeName; #define DECL_SPTR_FOR_SWIG(TypeName, MemberType) typedef std::shared_ptr TypeName; #define DECL_SET_FOR_SWIG(TypeName, MemberType) typedef std::set TypeName; diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index 6158ff00e3..8c819ff97f 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -102,7 +102,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_ } // convert graphic items on copper layers (texts) - for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) + for( auto item : m_drawings ) { if( !item->IsOnLayer( aLayer ) ) continue; diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 57f4ebd7ff..b8ef1e105d 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -913,9 +913,9 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode ) case PCB_TEXT_T: case PCB_TARGET_T: if( aMode == ADD_APPEND ) - m_Drawings.PushBack( aBoardItem ); + m_drawings.push_back( aBoardItem ); else - m_Drawings.PushFront( aBoardItem ); + m_drawings.push_front( aBoardItem ); break; @@ -989,7 +989,10 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem ) case PCB_LINE_T: case PCB_TEXT_T: case PCB_TARGET_T: - m_Drawings.Remove( aBoardItem ); + m_drawings.erase( + std::remove_if( m_drawings.begin(), m_drawings.end(), + [aBoardItem](BOARD_ITEM* aItem) + { return aItem == aBoardItem;} ) ); break; // other types may use linked list @@ -1101,7 +1104,7 @@ EDA_RECT BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const LSET visible = GetVisibleLayers(); // Check segments, dimensions, texts, and fiducials - for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) + for( auto item : m_drawings ) { if( aBoardEdgesOnly && (item->Type() != PCB_LINE_T || item->GetLayer() != Edge_Cuts ) ) continue; @@ -1263,7 +1266,7 @@ SEARCH_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const KICAD_T s case PCB_TEXT_T: case PCB_DIMENSION_T: case PCB_TARGET_T: - result = IterateForward( m_Drawings, inspector, testData, p ); + result = IterateForward( m_drawings, inspector, testData, p ); // skip over any types handled in the above call. for( ; ; ) diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 0ab16bfbf2..5e3ee965c3 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -161,6 +161,7 @@ protected: DECL_VEC_FOR_SWIG(MARKERS, MARKER_PCB*) DECL_VEC_FOR_SWIG(ZONE_CONTAINERS, ZONE_CONTAINER*) DECL_VEC_FOR_SWIG(TRACKS, TRACK*) +DECL_DEQ_FOR_SWIG(DRAWINGS, BOARD_ITEM*) /** @@ -178,6 +179,9 @@ private: /// MARKER_PCBs for clearance problems, owned by pointer. MARKERS m_markers; + /// BOARD_ITEMs for drawings on the board, owned by pointer. + DRAWINGS m_drawings; + /// edge zone descriptors, owned by pointer. ZONE_CONTAINERS m_ZoneDescriptorList; @@ -236,8 +240,8 @@ public: const wxString &GetFileName() const { return m_fileName; } -private: - DLIST m_Drawings; // linked list of lines & texts + /// Flags used in ratsnest calculation and update. + int m_Status_Pcb; public: @@ -246,13 +250,10 @@ public: DLIST_ITERATOR_WRAPPER Tracks() { return DLIST_ITERATOR_WRAPPER(m_Track); } DLIST_ITERATOR_WRAPPER Modules() { return DLIST_ITERATOR_WRAPPER(m_Modules); } - DLIST_ITERATOR_WRAPPER Drawings() { return DLIST_ITERATOR_WRAPPER(m_Drawings); } + DRAWINGS& Drawings() { return m_drawings; } ZONE_CONTAINERS& Zones() { return m_ZoneDescriptorList; } const std::vector AllConnectedItems(); - // will be deprecated as soon as append board functionality is fixed - DLIST& DrawingsList() { return m_Drawings; } - /// zone contour currently in progress ZONE_CONTAINER* m_CurrentZoneContour; @@ -264,7 +265,7 @@ public: bool IsEmpty() const { - return m_Drawings.GetCount() == 0 && m_Modules.GetCount() == 0 && m_Track.GetCount() == 0; + return m_drawings.empty() && m_Modules.GetCount() == 0 && m_Track.GetCount() == 0; } void Move( const wxPoint& aMoveVector ) override; diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 1930c4680b..b463bd700d 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -601,7 +601,7 @@ void PCB_IO::formatGeneral( BOARD* aBoard, int aNestLevel ) const m_out->Print( aNestLevel+1, "(thickness %s)\n", FormatInternalUnits( dsnSettings.GetBoardThickness() ).c_str() ); - m_out->Print( aNestLevel+1, "(drawings %d)\n", aBoard->Drawings().Size() ); + m_out->Print( aNestLevel+1, "(drawings %zu)\n", aBoard->Drawings().size() ); m_out->Print( aNestLevel+1, "(tracks %d)\n", aBoard->GetNumSegmTrack() ); m_out->Print( aNestLevel+1, "(modules %d)\n", aBoard->m_Modules.GetCount() ); m_out->Print( aNestLevel+1, "(nets %d)\n", m_mapping->GetSize() ); @@ -727,7 +727,7 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const for( auto item : aBoard->Drawings() ) Format( item, aNestLevel ); - if( aBoard->Drawings().Size() ) + if( aBoard->Drawings().size() ) m_out->Print( 0, "\n" ); // Do not save MARKER_PCBs, they can be regenerated easily. diff --git a/pcbnew/pcb_legacy_draw_utils.cpp b/pcbnew/pcb_legacy_draw_utils.cpp index 7520cc8926..8bccffe0c9 100644 --- a/pcbnew/pcb_legacy_draw_utils.cpp +++ b/pcbnew/pcb_legacy_draw_utils.cpp @@ -89,7 +89,7 @@ void BOARD::Print( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& offset ) } // Draw the graphic items - for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) + for( auto item : m_drawings ) { if( item->IsMoving() ) continue; diff --git a/pcbnew/swig/pcbnew_action_plugins.cpp b/pcbnew/swig/pcbnew_action_plugins.cpp index 2a4ee7e3b1..8053274a32 100644 --- a/pcbnew/swig/pcbnew_action_plugins.cpp +++ b/pcbnew/swig/pcbnew_action_plugins.cpp @@ -232,7 +232,7 @@ void PCB_EDIT_FRAME::RunActionPlugin( ACTION_PLUGIN* aActionPlugin ) } // Append drawings - for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() ) + for( auto item : currentPcb->Drawings() ) { ITEM_PICKER picker( item, UR_CHANGED ); itemsList.PushItem( picker ); @@ -354,7 +354,7 @@ void PCB_EDIT_FRAME::RunActionPlugin( ACTION_PLUGIN* aActionPlugin ) } } - for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() ) + for( auto item : currentPcb->Drawings() ) { if( !oldBuffer->ContainsItem( item ) ) { diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp index 7b9e538d6f..0e69d8729e 100644 --- a/pcbnew/tools/pcbnew_control.cpp +++ b/pcbnew/tools/pcbnew_control.cpp @@ -777,6 +777,23 @@ static void moveNoFlagToVector( DLIST& aList, std::vector& aTarg } } + +// Helper function for PCBNEW_CONTROL::placeBoardItems() +template +static void moveNoFlagToVector( std::deque& aList, std::vector& aTarget, bool aIsNew ) +{ + std::copy_if( aList.begin(), aList.end(), std::back_inserter( aTarget ), + [](T aItem){ + bool retval = aItem->GetFlags() & FLAG0; + aItem->ClearFlags( FLAG0 ); + return retval; + } ); + + if( aIsNew ) + aList.clear(); +} + + static void moveNoFlagToVector( ZONE_CONTAINERS& aList, std::vector& aTarget, bool aIsNew ) { if( aList.size() == 0 ) @@ -823,7 +840,7 @@ int PCBNEW_CONTROL::placeBoardItems( BOARD* aBoard ) moveNoFlagToVector( aBoard->m_Track, items, isNew ); moveNoFlagToVector( aBoard->m_Modules, items, isNew ); - moveNoFlagToVector( aBoard->DrawingsList(), items, isNew ); + moveNoFlagToVector( aBoard->Drawings(), items, isNew ); moveNoFlagToVector( aBoard->Zones(), items, isNew ); return placeBoardItems( items, isNew ); diff --git a/qa/pcbnew/CMakeLists.txt b/qa/pcbnew/CMakeLists.txt index f95c140297..b5f4260f20 100644 --- a/qa/pcbnew/CMakeLists.txt +++ b/qa/pcbnew/CMakeLists.txt @@ -64,6 +64,7 @@ target_link_libraries( qa_pcbnew legacy_gal gal common + gal qa_utils lib_dxf idf3