diff --git a/common/view/view.cpp b/common/view/view.cpp index 079f796570..55e1092da9 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -351,8 +351,81 @@ void VIEW::Add( VIEW_ITEM* aItem, int aDrawPriority ) } +static void DefragmentItems( std::vector& items ) +{ + size_t target = -1; + size_t sourceStart = -1; + size_t sourceEnd = -1; + + for( size_t ia = 0; ia < items.size(); ia++ ) + { + if( items[ia] == nullptr ) + { + if( sourceStart != -1 && target != -1 && sourceEnd != -1 ) + { + int len = sourceEnd - sourceStart + 1; + + memmove( &items[target], &items[sourceStart], sizeof( items[0] ) * len ); + + target += len; + + sourceStart = -1; + sourceEnd = -1; + } + + if( target == -1 ) + target = ia; + } + else + { + if( target != -1 ) + { + if( sourceStart == -1 ) + sourceStart = ia; + + sourceEnd = ia; + } + } + } + + if( sourceStart != -1 && target != -1 && sourceEnd != -1 ) + { + int len = sourceEnd - sourceStart + 1; + + memmove( &items[target], &items[sourceStart], sizeof( items[0] ) * len ); + + target += len; + + sourceStart = -1; + sourceEnd = -1; + } + + int needSize = 0; + + if( target != -1 ) + { + needSize = target; + } + else + { + for( int in = int( items.size() ) - 1; in >= 0; in-- ) + { + if( items[in] != nullptr ) + { + needSize = in + 1; + break; + } + } + } + + items.resize( needSize ); +} + + void VIEW::Remove( VIEW_ITEM* aItem ) { + static int s_gcCounter = 0; + if( aItem && aItem->m_viewPrivData ) { wxCHECK( aItem->m_viewPrivData->m_view == this, /*void*/ ); @@ -360,8 +433,16 @@ void VIEW::Remove( VIEW_ITEM* aItem ) if( item != m_allItems->end() ) { - m_allItems->erase( item ); + *item = nullptr; aItem->m_viewPrivData->clearUpdateFlags(); + + s_gcCounter++; + + if( s_gcCounter > 4096 ) + { + DefragmentItems( *m_allItems ); + s_gcCounter = 0; + } } int layers[VIEW::VIEW_MAX_LAYERS], layers_count; @@ -696,6 +777,9 @@ void VIEW::ReorderLayerData( std::unordered_map aReorderMap ) for( VIEW_ITEM* item : *m_allItems ) { + if( !item ) + continue; + VIEW_ITEM_DATA* viewData = item->viewPrivData(); if( !viewData ) @@ -771,6 +855,9 @@ void VIEW::UpdateAllLayersColor() for( VIEW_ITEM* item : *m_allItems ) { + if( !item ) + continue; + VIEW_ITEM_DATA* viewData = item->viewPrivData(); if( !viewData ) @@ -904,6 +991,9 @@ void VIEW::UpdateAllLayersOrder() for( VIEW_ITEM* item : *m_allItems ) { + if( !item ) + continue; + VIEW_ITEM_DATA* viewData = item->viewPrivData(); if( !viewData ) @@ -1434,6 +1524,9 @@ void VIEW::UpdateItems() for( VIEW_ITEM* item : *m_allItems ) { + if( !item ) + continue; + auto vpd = item->viewPrivData(); if( !vpd ) @@ -1472,6 +1565,9 @@ void VIEW::UpdateItems() // and re-insert items from scratch for( VIEW_ITEM* item : allItems ) { + if( !item ) + continue; + const BOX2I bbox = item->ViewBBox(); item->m_viewPrivData->m_bbox = bbox; @@ -1497,7 +1593,7 @@ void VIEW::UpdateItems() for( VIEW_ITEM* item : *m_allItems.get() ) { - if( item->viewPrivData() && item->viewPrivData()->m_requiredUpdate != NONE ) + if( item && item->viewPrivData() && item->viewPrivData()->m_requiredUpdate != NONE ) { invalidateItem( item, item->viewPrivData()->m_requiredUpdate ); item->viewPrivData()->m_requiredUpdate = NONE; @@ -1514,7 +1610,7 @@ void VIEW::UpdateAllItems( int aUpdateFlags ) { for( VIEW_ITEM* item : *m_allItems ) { - if( item->viewPrivData() ) + if( item && item->viewPrivData() ) item->viewPrivData()->m_requiredUpdate |= aUpdateFlags; } } @@ -1525,6 +1621,9 @@ void VIEW::UpdateAllItemsConditionally( int aUpdateFlags, { for( VIEW_ITEM* item : *m_allItems ) { + if( !item ) + continue; + if( aCondition( item ) ) { if( item->viewPrivData() ) @@ -1538,6 +1637,9 @@ void VIEW::UpdateAllItemsConditionally( std::function aItemFl { for( VIEW_ITEM* item : *m_allItems ) { + if( !item ) + continue; + if( item->viewPrivData() ) item->viewPrivData()->m_requiredUpdate |= aItemFlagsProvider( item ); }