149 const std::set<DRC_CONSTRAINT_T>& aClaimedConstraints )
155 auto data = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>();
156 data->SetRuleName( aRule.
m_Name );
157 data->SetConstraintCode(
"via_style" );
178 if( expr.Contains( wxS(
"'Micro'" ) ) )
180 else if( expr.Contains( wxS(
"'Through'" ) ) )
182 else if( expr.Contains( wxS(
"'Blind'" ) ) )
184 else if( expr.Contains( wxS(
"'Buried'" ) ) )
188 wxString cleanedCondition = expr;
189 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Micro'" ), wxS(
"" ) );
190 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Through'" ), wxS(
"" ) );
191 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Blind'" ), wxS(
"" ) );
192 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Buried'" ), wxS(
"" ) );
202 auto data = std::make_shared<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>();
203 data->SetRuleName( aRule.
m_Name );
204 data->SetConstraintCode(
"diff_pair_gap" );
214 data->SetOptWidth( opt );
215 data->SetWidthTolerance( opt - min );
222 data->SetOptGap( opt );
223 data->SetGapTolerance( opt - min );
236 auto data = std::make_shared<DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA>();
237 data->SetRuleName( aRule.
m_Name );
238 data->SetConstraintCode(
"text_height" );
254 auto data = std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>();
255 data->SetRuleName( aRule.
m_Name );
256 data->SetConstraintCode(
"track_width" );
266 data->SetOptWidth( opt );
270 double tolFromMin = opt - min;
271 double tolFromMax = max - opt;
272 data->SetWidthTolerance( std::max( tolFromMin, tolFromMax ) );
281 auto data = std::make_shared<DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA>();
282 data->SetRuleName( aRule.
m_Name );
283 data->SetConstraintCode(
"length" );
292 data->SetOptimumLength( optMM );
293 data->SetTolerance( ( maxMM - minMM ) / 2.0 );
301 auto data = std::make_shared<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>();
302 data->SetRuleName( aRule.
m_Name );
303 data->SetConstraintCode(
"length" );
312 data->SetOptimumLength( optMM );
313 data->SetTolerance( ( maxMM - minMM ) / 2.0 );
329 auto data = std::make_shared<DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA>();
330 data->SetRuleName( aRule.
m_Name );
334 if( constraint && constraint->
m_Test )
338 data->SetTopLayerEnabled( expr.Contains( wxS(
"F.Cu" ) ) );
339 data->SetBottomLayerEnabled( expr.Contains( wxS(
"B.Cu" ) ) );
342 wxString remaining = expr;
343 remaining.Replace( wxS(
"A.Layer == 'F.Cu'" ), wxS(
"" ) );
344 remaining.Replace( wxS(
"A.Layer == 'B.Cu'" ), wxS(
"" ) );
346 if( remaining.Contains( wxS(
"A.Layer" ) ) )
349 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
350 customData->SetRuleName( aRule.
m_Name );
360 auto data = std::make_shared<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>();
361 data->SetRuleName( aRule.
m_Name );
362 data->SetConstraintCode( wxS(
"allowed_orientation" ) );
366 if( constraint && constraint->
m_Test )
370 data->SetIsZeroDegreesAllowed( expr.Contains( wxS(
"== 0 deg" ) ) );
371 data->SetIsNinetyDegreesAllowed( expr.Contains( wxS(
"== 90 deg" ) ) );
372 data->SetIsOneEightyDegreesAllowed( expr.Contains( wxS(
"== 180 deg" ) ) );
373 data->SetIsTwoSeventyDegreesAllowed( expr.Contains( wxS(
"== 270 deg" ) ) );
375 if( data->GetIsZeroDegreesAllowed() && data->GetIsNinetyDegreesAllowed()
376 && data->GetIsOneEightyDegreesAllowed() && data->GetIsTwoSeventyDegreesAllowed() )
378 data->SetIsAllDegreesAllowed(
true );
382 if( data->GetIsZeroDegreesAllowed() || data->GetIsNinetyDegreesAllowed()
383 || data->GetIsOneEightyDegreesAllowed() || data->GetIsTwoSeventyDegreesAllowed() )
390 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
391 customData->SetRuleName( aRule.
m_Name );
396 data->SetIsAllDegreesAllowed(
true );
404 auto data = std::make_shared<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>();
405 data->SetRuleName( aRule.
m_Name );
406 data->SetConstraintCode( wxS(
"disallow_via" ) );
423 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
424 data->SetRuleName( aRule.
m_Name );
434 data->SetRuleName( aRule.
m_Name );
437 data->SetConstraintCode( code );
447 data->SetNumericInputValue( constraint->
GetValue().
Max() );
449 data->SetNumericInputValue( constraint->
GetValue().
Min() );
461 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
462 data->SetRuleName( aRule.
m_Name );
470 const wxString& aOriginalText )
472 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries;
481 std::vector<DRC_PANEL_MATCH> matches =
m_matcher.MatchRule( aRule );
489 if( assertion && assertion->
m_Test )
493 if( expr.Contains( wxS(
"Orientation" ) ) && !expr.Contains( wxS(
"Layer" ) ) )
500 if( !condition.IsEmpty()
501 && ( condition.Contains( wxS(
"L == 'F.Mask'" ) ) || condition.Contains( wxS(
"L == 'B.Mask'" ) ) ) )
505 else if( !condition.IsEmpty() && !condition.Contains( wxS(
"L == 'F.SilkS'" ) )
506 && !condition.Contains( wxS(
"L == 'B.SilkS'" ) ) )
514 if( !constraintData )
519 auto customFallback = std::dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( constraintData );
521 if( customFallback && match.panelType !=
CUSTOM_RULE )
528 wxString cleanedCondition = condition;
531 bool hasBothSides = condition.Contains( wxS(
"L == 'F.Mask' || L == 'B.Mask'" ) );
536 constraintData->SetLayerSource( wxS(
"" ) );
538 cleanedCondition.Replace( wxS(
"L == 'F.Mask' || L == 'B.Mask'" ), wxS(
"" ) );
542 bool isFront = condition.Contains( wxS(
"F.Mask" ) );
544 constraintData->SetLayers( { layer } );
545 constraintData->SetLayerSource( isFront ? wxS(
"F.SilkS" ) : wxS(
"B.SilkS" ) );
547 cleanedCondition.Replace( wxS(
"L == 'F.Mask'" ), wxS(
"" ) );
548 cleanedCondition.Replace( wxS(
"L == 'B.Mask'" ), wxS(
"" ) );
556 wxString cleanedCondition = condition;
558 bool hasBothSides = condition.Contains( wxS(
"L == 'F.SilkS' || L == 'B.SilkS'" ) );
563 constraintData->SetLayerSource( wxS(
"" ) );
565 cleanedCondition.Replace( wxS(
"L == 'F.SilkS' || L == 'B.SilkS'" ), wxS(
"" ) );
567 else if( condition.Contains( wxS(
"L == 'F.SilkS'" ) ) || condition.Contains( wxS(
"L == 'B.SilkS'" ) ) )
569 bool isFront = condition.Contains( wxS(
"F.SilkS" ) );
571 constraintData->SetLayers( { layer } );
572 constraintData->SetLayerSource( isFront ? wxS(
"F.SilkS" ) : wxS(
"B.SilkS" ) );
574 cleanedCondition.Replace( wxS(
"L == 'F.SilkS'" ), wxS(
"" ) );
575 cleanedCondition.Replace( wxS(
"L == 'B.SilkS'" ), wxS(
"" ) );
583 wxString cleanedCondition = condition;
585 cleanedCondition.Replace( wxS(
"A.Pad_Type == 'SMD'" ), wxS(
"" ) );
586 cleanedCondition.Replace( wxS(
"B.Pad_Type == 'SMD'" ), wxS(
"" ) );
591 if( match.panelType ==
CUSTOM_RULE && customFallback )
598 constraintData->SetRuleCondition( condition );
605 if( source.StartsWith( wxS(
"'" ) ) && source.EndsWith( wxS(
"'" ) ) )
606 source = source.Mid( 1, source.Length() - 2 );
610 if( !comment.IsEmpty() )
611 constraintData->SetComment( comment );
614 if( entries.empty() )
617 entries.push_back( std::move( entry ) );
621 if( entries.empty() )
623 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
624 customData->SetRuleName( aRule.
m_Name );
625 customData->SetRuleCondition( condition );
628 if( !comment.IsEmpty() )
629 customData->SetComment( comment );
636 if( source.StartsWith( wxS(
"'" ) ) && source.EndsWith( wxS(
"'" ) ) )
637 source = source.Mid( 1, source.Length() - 2 );
640 entries.push_back( std::move( entry ) );
688 wxString quotedSearch = wxString::Format( wxS(
"(rule \"%s\"" ), aRuleName );
689 wxString unquotedSearch = wxString::Format( wxS(
"(rule %s" ), aRuleName );
691 size_t startPos = aContent.find( quotedSearch );
693 if( startPos == wxString::npos )
697 while( ( pos = aContent.find( unquotedSearch, pos ) ) != wxString::npos )
699 size_t afterMatch = pos + unquotedSearch.length();
701 if( afterMatch >= aContent.length()
702 || aContent[afterMatch] ==
')'
703 || aContent[afterMatch] ==
' '
704 || aContent[afterMatch] ==
'\n'
705 || aContent[afterMatch] ==
'\r'
706 || aContent[afterMatch] ==
'\t' )
716 if( startPos == wxString::npos )
717 return wxEmptyString;
721 size_t endPos = startPos;
722 bool inString =
false;
723 bool escaped =
false;
725 for(
size_t i = startPos; i < aContent.length(); ++i )
727 wxUniChar c = aContent[i];
743 inString = !inString;
758 if( parenCount == 0 )
766 if( parenCount != 0 )
767 return wxEmptyString;
769 return aContent.Mid( startPos, endPos - startPos + 1 );
Represents a rule loaded from a .kicad_dru file and mapped to a panel.
wxString layerSource
Original layer text: "inner", "outer", or layer name.