167 const std::set<DRC_CONSTRAINT_T>& aClaimedConstraints )
173 auto data = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>();
174 data->SetRuleName( aRule.
m_Name );
175 data->SetConstraintCode(
"via_style" );
196 if( expr.Contains( wxS(
"'Micro'" ) ) )
198 else if( expr.Contains( wxS(
"'Through'" ) ) )
200 else if( expr.Contains( wxS(
"'Blind'" ) ) )
202 else if( expr.Contains( wxS(
"'Buried'" ) ) )
206 wxString cleanedCondition = expr;
207 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Micro'" ), wxS(
"" ) );
208 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Through'" ), wxS(
"" ) );
209 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Blind'" ), wxS(
"" ) );
210 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Buried'" ), wxS(
"" ) );
229 auto data = std::make_shared<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>();
230 data->SetRuleName( aRule.
m_Name );
231 data->SetConstraintCode(
"diff_pair_gap" );
237 data->SetOptWidth( opt );
238 data->SetWidthTolerance( opt - min );
245 data->SetOptGap( opt );
246 data->SetGapTolerance( opt - min );
259 auto data = std::make_shared<DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA>();
260 data->SetRuleName( aRule.
m_Name );
261 data->SetConstraintCode(
"text_height" );
282 auto data = std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>();
283 data->SetRuleName( aRule.
m_Name );
284 data->SetConstraintCode(
"track_width" );
291 data->SetOptWidth( opt );
292 data->SetWidthTolerance( opt - min );
305 auto data = std::make_shared<DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA>();
306 data->SetRuleName( aRule.
m_Name );
307 data->SetConstraintCode(
"length" );
314 data->SetOptimumLength( optMM );
315 data->SetTolerance( ( maxMM - minMM ) / 2.0 );
328 auto data = std::make_shared<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>();
329 data->SetRuleName( aRule.
m_Name );
330 data->SetConstraintCode(
"length" );
337 data->SetOptimumLength( optMM );
338 data->SetTolerance( ( maxMM - minMM ) / 2.0 );
354 auto data = std::make_shared<DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA>();
355 data->SetRuleName( aRule.
m_Name );
359 if( constraint && constraint->
m_Test )
363 data->SetTopLayerEnabled( expr.Contains( wxS(
"F.Cu" ) ) );
364 data->SetBottomLayerEnabled( expr.Contains( wxS(
"B.Cu" ) ) );
367 wxString remaining = expr;
368 remaining.Replace( wxS(
"A.Layer == 'F.Cu'" ), wxS(
"" ) );
369 remaining.Replace( wxS(
"A.Layer == 'B.Cu'" ), wxS(
"" ) );
371 if( remaining.Contains( wxS(
"A.Layer" ) ) )
374 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
375 customData->SetRuleName( aRule.
m_Name );
385 auto data = std::make_shared<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>();
386 data->SetRuleName( aRule.
m_Name );
387 data->SetConstraintCode( wxS(
"allowed_orientation" ) );
391 if( constraint && constraint->
m_Test )
395 data->SetIsZeroDegreesAllowed( expr.Contains( wxS(
"== 0 deg" ) ) );
396 data->SetIsNinetyDegreesAllowed( expr.Contains( wxS(
"== 90 deg" ) ) );
397 data->SetIsOneEightyDegreesAllowed( expr.Contains( wxS(
"== 180 deg" ) ) );
398 data->SetIsTwoSeventyDegreesAllowed( expr.Contains( wxS(
"== 270 deg" ) ) );
400 if( data->GetIsZeroDegreesAllowed() && data->GetIsNinetyDegreesAllowed()
401 && data->GetIsOneEightyDegreesAllowed() && data->GetIsTwoSeventyDegreesAllowed() )
403 data->SetIsAllDegreesAllowed(
true );
407 if( data->GetIsZeroDegreesAllowed() || data->GetIsNinetyDegreesAllowed()
408 || data->GetIsOneEightyDegreesAllowed() || data->GetIsTwoSeventyDegreesAllowed() )
415 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
416 customData->SetRuleName( aRule.
m_Name );
421 data->SetIsAllDegreesAllowed(
true );
429 auto data = std::make_shared<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>();
430 data->SetRuleName( aRule.
m_Name );
431 data->SetConstraintCode( wxS(
"disallow_via" ) );
448 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
449 data->SetRuleName( aRule.
m_Name );
459 data->SetRuleName( aRule.
m_Name );
462 data->SetConstraintCode( code );
472 data->SetNumericInputValue( constraint->
GetValue().
Max() );
474 data->SetNumericInputValue( constraint->
GetValue().
Min() );
486 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
487 data->SetRuleName( aRule.
m_Name );
495 const wxString& aOriginalText )
497 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries;
506 std::vector<DRC_PANEL_MATCH> matches =
m_matcher.MatchRule( aRule );
514 if( assertion && assertion->
m_Test )
518 if( expr.Contains( wxS(
"Orientation" ) ) && !expr.Contains( wxS(
"Layer" ) ) )
525 if( !condition.IsEmpty()
526 && ( condition.Contains( wxS(
"L == 'F.Mask'" ) ) || condition.Contains( wxS(
"L == 'B.Mask'" ) ) ) )
530 else if( !condition.IsEmpty() && !condition.Contains( wxS(
"L == 'F.SilkS'" ) )
531 && !condition.Contains( wxS(
"L == 'B.SilkS'" ) ) )
539 if( !constraintData )
544 auto customFallback = std::dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( constraintData );
546 if( customFallback && match.panelType !=
CUSTOM_RULE )
553 wxString cleanedCondition = condition;
556 bool hasBothSides = condition.Contains( wxS(
"L == 'F.Mask' || L == 'B.Mask'" ) );
561 constraintData->SetLayerSource( wxS(
"" ) );
563 cleanedCondition.Replace( wxS(
"L == 'F.Mask' || L == 'B.Mask'" ), wxS(
"" ) );
567 bool isFront = condition.Contains( wxS(
"F.Mask" ) );
569 constraintData->SetLayers( { layer } );
570 constraintData->SetLayerSource( isFront ? wxS(
"F.SilkS" ) : wxS(
"B.SilkS" ) );
572 cleanedCondition.Replace( wxS(
"L == 'F.Mask'" ), wxS(
"" ) );
573 cleanedCondition.Replace( wxS(
"L == 'B.Mask'" ), wxS(
"" ) );
581 wxString cleanedCondition = condition;
583 bool hasBothSides = condition.Contains( wxS(
"L == 'F.SilkS' || L == 'B.SilkS'" ) );
588 constraintData->SetLayerSource( wxS(
"" ) );
590 cleanedCondition.Replace( wxS(
"L == 'F.SilkS' || L == 'B.SilkS'" ), wxS(
"" ) );
592 else if( condition.Contains( wxS(
"L == 'F.SilkS'" ) ) || condition.Contains( wxS(
"L == 'B.SilkS'" ) ) )
594 bool isFront = condition.Contains( wxS(
"F.SilkS" ) );
596 constraintData->SetLayers( { layer } );
597 constraintData->SetLayerSource( isFront ? wxS(
"F.SilkS" ) : wxS(
"B.SilkS" ) );
599 cleanedCondition.Replace( wxS(
"L == 'F.SilkS'" ), wxS(
"" ) );
600 cleanedCondition.Replace( wxS(
"L == 'B.SilkS'" ), wxS(
"" ) );
608 wxString cleanedCondition = condition;
610 cleanedCondition.Replace( wxS(
"A.Pad_Type == 'SMD'" ), wxS(
"" ) );
611 cleanedCondition.Replace( wxS(
"B.Pad_Type == 'SMD'" ), wxS(
"" ) );
616 if( match.panelType ==
CUSTOM_RULE && customFallback )
623 constraintData->SetRuleCondition( condition );
630 if( source.StartsWith( wxS(
"'" ) ) && source.EndsWith( wxS(
"'" ) ) )
631 source = source.Mid( 1, source.Length() - 2 );
635 if( !comment.IsEmpty() )
636 constraintData->SetComment( comment );
639 if( entries.empty() )
642 entries.push_back( std::move( entry ) );
646 if( entries.empty() )
648 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
649 customData->SetRuleName( aRule.
m_Name );
650 customData->SetRuleCondition( condition );
653 if( !comment.IsEmpty() )
654 customData->SetComment( comment );
661 if( source.StartsWith( wxS(
"'" ) ) && source.EndsWith( wxS(
"'" ) ) )
662 source = source.Mid( 1, source.Length() - 2 );
665 entries.push_back( std::move( entry ) );
713 wxString quotedSearch = wxString::Format( wxS(
"(rule \"%s\"" ), aRuleName );
714 wxString unquotedSearch = wxString::Format( wxS(
"(rule %s" ), aRuleName );
716 size_t startPos = aContent.find( quotedSearch );
718 if( startPos == wxString::npos )
722 while( ( pos = aContent.find( unquotedSearch, pos ) ) != wxString::npos )
724 size_t afterMatch = pos + unquotedSearch.length();
726 if( afterMatch >= aContent.length()
727 || aContent[afterMatch] ==
')'
728 || aContent[afterMatch] ==
' '
729 || aContent[afterMatch] ==
'\n'
730 || aContent[afterMatch] ==
'\r'
731 || aContent[afterMatch] ==
'\t' )
741 if( startPos == wxString::npos )
742 return wxEmptyString;
746 size_t endPos = startPos;
747 bool inString =
false;
748 bool escaped =
false;
750 for(
size_t i = startPos; i < aContent.length(); ++i )
752 wxUniChar c = aContent[i];
768 inString = !inString;
783 if( parenCount == 0 )
791 if( parenCount != 0 )
792 return wxEmptyString;
794 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.