171 const std::set<DRC_CONSTRAINT_T>& aClaimedConstraints )
177 auto data = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>();
178 data->SetRuleName( aRule.
m_Name );
179 data->SetConstraintCode(
"via_style" );
200 if( expr.Contains( wxS(
"'Micro'" ) ) )
202 else if( expr.Contains( wxS(
"'Through'" ) ) )
204 else if( expr.Contains( wxS(
"'Blind'" ) ) )
206 else if( expr.Contains( wxS(
"'Buried'" ) ) )
210 wxString cleanedCondition = expr;
211 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Micro'" ), wxS(
"" ) );
212 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Through'" ), wxS(
"" ) );
213 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Blind'" ), wxS(
"" ) );
214 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Buried'" ), wxS(
"" ) );
233 auto data = std::make_shared<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>();
234 data->SetRuleName( aRule.
m_Name );
235 data->SetConstraintCode(
"diff_pair_gap" );
241 data->SetOptWidth( opt );
242 data->SetWidthTolerance( opt - min );
249 data->SetOptGap( opt );
250 data->SetGapTolerance( opt - min );
263 auto data = std::make_shared<DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA>();
264 data->SetRuleName( aRule.
m_Name );
265 data->SetConstraintCode(
"text_height" );
286 auto data = std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>();
287 data->SetRuleName( aRule.
m_Name );
288 data->SetConstraintCode(
"track_width" );
295 data->SetOptWidth( opt );
296 data->SetWidthTolerance( opt - min );
309 auto data = std::make_shared<DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA>();
310 data->SetRuleName( aRule.
m_Name );
311 data->SetConstraintCode(
"length" );
318 data->SetOptimumLength( optMM );
319 data->SetTolerance( ( maxMM - minMM ) / 2.0 );
332 auto data = std::make_shared<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>();
333 data->SetRuleName( aRule.
m_Name );
334 data->SetConstraintCode(
"length" );
341 data->SetOptimumLength( optMM );
342 data->SetTolerance( ( maxMM - minMM ) / 2.0 );
358 auto data = std::make_shared<DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA>();
359 data->SetRuleName( aRule.
m_Name );
363 if( constraint && constraint->
m_Test )
367 data->SetTopLayerEnabled( expr.Contains( wxS(
"F.Cu" ) ) );
368 data->SetBottomLayerEnabled( expr.Contains( wxS(
"B.Cu" ) ) );
371 wxString remaining = expr;
372 remaining.Replace( wxS(
"A.Layer == 'F.Cu'" ), wxS(
"" ) );
373 remaining.Replace( wxS(
"A.Layer == 'B.Cu'" ), wxS(
"" ) );
375 if( remaining.Contains( wxS(
"A.Layer" ) ) )
378 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
379 customData->SetRuleName( aRule.
m_Name );
389 auto data = std::make_shared<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>();
390 data->SetRuleName( aRule.
m_Name );
391 data->SetConstraintCode( wxS(
"allowed_orientation" ) );
395 if( constraint && constraint->
m_Test )
399 data->SetIsZeroDegreesAllowed( expr.Contains( wxS(
"== 0 deg" ) ) );
400 data->SetIsNinetyDegreesAllowed( expr.Contains( wxS(
"== 90 deg" ) ) );
401 data->SetIsOneEightyDegreesAllowed( expr.Contains( wxS(
"== 180 deg" ) ) );
402 data->SetIsTwoSeventyDegreesAllowed( expr.Contains( wxS(
"== 270 deg" ) ) );
404 if( data->GetIsZeroDegreesAllowed() && data->GetIsNinetyDegreesAllowed()
405 && data->GetIsOneEightyDegreesAllowed() && data->GetIsTwoSeventyDegreesAllowed() )
407 data->SetIsAllDegreesAllowed(
true );
411 if( data->GetIsZeroDegreesAllowed() || data->GetIsNinetyDegreesAllowed()
412 || data->GetIsOneEightyDegreesAllowed() || data->GetIsTwoSeventyDegreesAllowed() )
419 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
420 customData->SetRuleName( aRule.
m_Name );
425 data->SetIsAllDegreesAllowed(
true );
433 auto data = std::make_shared<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>();
434 data->SetRuleName( aRule.
m_Name );
435 data->SetConstraintCode( wxS(
"disallow_via" ) );
452 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
453 data->SetRuleName( aRule.
m_Name );
463 data->SetRuleName( aRule.
m_Name );
466 data->SetConstraintCode( code );
476 data->SetNumericInputValue( constraint->
GetValue().
Max() );
478 data->SetNumericInputValue( constraint->
GetValue().
Min() );
490 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
491 data->SetRuleName( aRule.
m_Name );
499 const wxString& aOriginalText )
501 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries;
510 std::vector<DRC_PANEL_MATCH> matches =
m_matcher.MatchRule( aRule );
518 if( assertion && assertion->
m_Test )
522 if( expr.Contains( wxS(
"Orientation" ) ) && !expr.Contains( wxS(
"Layer" ) ) )
529 if( !condition.IsEmpty()
530 && ( condition.Contains( wxS(
"L == 'F.Mask'" ) ) || condition.Contains( wxS(
"L == 'B.Mask'" ) ) ) )
534 else if( !condition.IsEmpty() && !condition.Contains( wxS(
"L == 'F.SilkS'" ) )
535 && !condition.Contains( wxS(
"L == 'B.SilkS'" ) ) )
543 if( !constraintData )
548 auto customFallback = std::dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( constraintData );
550 if( customFallback && match.panelType !=
CUSTOM_RULE )
557 wxString cleanedCondition = condition;
560 bool hasBothSides = condition.Contains( wxS(
"L == 'F.Mask' || L == 'B.Mask'" ) );
565 constraintData->SetLayerSource( wxS(
"" ) );
567 cleanedCondition.Replace( wxS(
"L == 'F.Mask' || L == 'B.Mask'" ), wxS(
"" ) );
571 bool isFront = condition.Contains( wxS(
"F.Mask" ) );
573 constraintData->SetLayers( { layer } );
574 constraintData->SetLayerSource( isFront ? wxS(
"F.SilkS" ) : wxS(
"B.SilkS" ) );
576 cleanedCondition.Replace( wxS(
"L == 'F.Mask'" ), wxS(
"" ) );
577 cleanedCondition.Replace( wxS(
"L == 'B.Mask'" ), wxS(
"" ) );
585 wxString cleanedCondition = condition;
587 bool hasBothSides = condition.Contains( wxS(
"L == 'F.SilkS' || L == 'B.SilkS'" ) );
592 constraintData->SetLayerSource( wxS(
"" ) );
594 cleanedCondition.Replace( wxS(
"L == 'F.SilkS' || L == 'B.SilkS'" ), wxS(
"" ) );
596 else if( condition.Contains( wxS(
"L == 'F.SilkS'" ) ) || condition.Contains( wxS(
"L == 'B.SilkS'" ) ) )
598 bool isFront = condition.Contains( wxS(
"F.SilkS" ) );
600 constraintData->SetLayers( { layer } );
601 constraintData->SetLayerSource( isFront ? wxS(
"F.SilkS" ) : wxS(
"B.SilkS" ) );
603 cleanedCondition.Replace( wxS(
"L == 'F.SilkS'" ), wxS(
"" ) );
604 cleanedCondition.Replace( wxS(
"L == 'B.SilkS'" ), wxS(
"" ) );
612 wxString cleanedCondition = condition;
614 cleanedCondition.Replace( wxS(
"A.Pad_Type == 'SMD'" ), wxS(
"" ) );
615 cleanedCondition.Replace( wxS(
"B.Pad_Type == 'SMD'" ), wxS(
"" ) );
620 if( match.panelType ==
CUSTOM_RULE && customFallback )
627 constraintData->SetRuleCondition( condition );
634 if( source.StartsWith( wxS(
"'" ) ) && source.EndsWith( wxS(
"'" ) ) )
635 source = source.Mid( 1, source.Length() - 2 );
639 if( !comment.IsEmpty() )
640 constraintData->SetComment( comment );
643 if( entries.empty() )
646 entries.push_back( std::move( entry ) );
650 if( entries.empty() )
652 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
653 customData->SetRuleName( aRule.
m_Name );
654 customData->SetRuleCondition( condition );
657 if( !comment.IsEmpty() )
658 customData->SetComment( comment );
665 if( source.StartsWith( wxS(
"'" ) ) && source.EndsWith( wxS(
"'" ) ) )
666 source = source.Mid( 1, source.Length() - 2 );
669 entries.push_back( std::move( entry ) );
717 wxString quotedSearch = wxString::Format( wxS(
"(rule \"%s\"" ), aRuleName );
718 wxString unquotedSearch = wxString::Format( wxS(
"(rule %s" ), aRuleName );
720 size_t startPos = aContent.find( quotedSearch );
722 if( startPos == wxString::npos )
726 while( ( pos = aContent.find( unquotedSearch, pos ) ) != wxString::npos )
728 size_t afterMatch = pos + unquotedSearch.length();
730 if( afterMatch >= aContent.length()
731 || aContent[afterMatch] ==
')'
732 || aContent[afterMatch] ==
' '
733 || aContent[afterMatch] ==
'\n'
734 || aContent[afterMatch] ==
'\r'
735 || aContent[afterMatch] ==
'\t' )
745 if( startPos == wxString::npos )
746 return wxEmptyString;
750 size_t endPos = startPos;
751 bool inString =
false;
752 bool escaped =
false;
754 for(
size_t i = startPos; i < aContent.length(); ++i )
756 wxUniChar c = aContent[i];
772 inString = !inString;
787 if( parenCount == 0 )
795 if( parenCount != 0 )
796 return wxEmptyString;
798 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.