diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index b2f505bb82..783c8384f7 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -198,6 +198,7 @@ void BOARD::IncrementTimeStamp() m_InsideCourtyardCache.clear(); m_InsideFCourtyardCache.clear(); m_InsideBCourtyardCache.clear(); + m_LayerExpressionCache.clear(); } m_CopperZoneRTrees.clear(); diff --git a/pcbnew/board.h b/pcbnew/board.h index 6eb1aac897..87520c4473 100644 --- a/pcbnew/board.h +++ b/pcbnew/board.h @@ -1084,6 +1084,7 @@ public: std::map< std::pair, bool > m_InsideFCourtyardCache; std::map< std::pair, bool > m_InsideBCourtyardCache; std::map< std::pair, bool > m_InsideAreaCache; + std::map< wxString, LSET > m_LayerExpressionCache; std::map< ZONE*, std::unique_ptr > m_CopperZoneRTrees; diff --git a/pcbnew/pcb_expr_evaluator.cpp b/pcbnew/pcb_expr_evaluator.cpp index b29778181f..2189f9e9ff 100644 --- a/pcbnew/pcb_expr_evaluator.cpp +++ b/pcbnew/pcb_expr_evaluator.cpp @@ -100,26 +100,65 @@ static void existsOnLayer( LIBEVAL::CONTEXT* aCtx, void *self ) wxString layerName = arg->AsString(); wxPGChoices& layerMap = ENUM_MAP::Instance().Choices(); - bool anyMatch = false; - for( unsigned ii = 0; ii < layerMap.GetCount(); ++ii ) + if( aCtx->HasErrorCallback() ) { - wxPGChoiceEntry& entry = layerMap[ii]; + /* + * Interpreted version + */ - if( entry.GetText().Matches( layerName ) ) + bool anyMatch = false; + + for( unsigned ii = 0; ii < layerMap.GetCount(); ++ii ) { - anyMatch = true; + wxPGChoiceEntry& entry = layerMap[ii]; - if( item->IsOnLayer( ToLAYER_ID( entry.GetValue() ) ) ) + if( entry.GetText().Matches( layerName ) ) { - result->Set( 1.0 ); - return; + anyMatch = true; + + if( item->IsOnLayer( ToLAYER_ID( entry.GetValue() ) ) ) + { + result->Set( 1.0 ); + return; + } } } - } - if( !anyMatch && aCtx->HasErrorCallback() ) - aCtx->ReportError( wxString::Format( _( "Unrecognized layer '%s'" ), layerName ) ); + if( !anyMatch ) + aCtx->ReportError( wxString::Format( _( "Unrecognized layer '%s'" ), layerName ) ); + } + else + { + /* + * Compiled version + */ + + BOARD* board = item->GetBoard(); + std::unique_lock cacheLock( board->m_CachesMutex ); + auto i = board->m_LayerExpressionCache.find( layerName ); + LSET mask; + + if( i == board->m_LayerExpressionCache.end() ) + { + for( unsigned ii = 0; ii < layerMap.GetCount(); ++ii ) + { + wxPGChoiceEntry& entry = layerMap[ii]; + + if( entry.GetText().Matches( layerName ) ) + mask.set( ToLAYER_ID( entry.GetValue() ) ); + } + + board->m_LayerExpressionCache[ layerName ] = mask; + } + else + { + mask = i->second; + } + + if( ( item->GetLayerSet() & mask ).any() ) + result->Set( 1.0 ); + } }