188 const std::set<DRC_CONSTRAINT_T>& aClaimedConstraints )
194 auto data = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>();
195 data->SetRuleName( aRule.
m_Name );
196 data->SetConstraintCode(
"via_style" );
217 if( expr.Contains( wxS(
"'Micro'" ) ) )
219 else if( expr.Contains( wxS(
"'Through'" ) ) )
221 else if( expr.Contains( wxS(
"'Blind'" ) ) )
223 else if( expr.Contains( wxS(
"'Buried'" ) ) )
227 wxString cleanedCondition = expr;
228 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Micro'" ), wxS(
"" ) );
229 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Through'" ), wxS(
"" ) );
230 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Blind'" ), wxS(
"" ) );
231 cleanedCondition.Replace( wxS(
"A.Via_Type == 'Buried'" ), wxS(
"" ) );
250 auto data = std::make_shared<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>();
251 data->SetRuleName( aRule.
m_Name );
252 data->SetConstraintCode(
"diff_pair_gap" );
259 data->SetOptWidth( opt );
260 data->SetWidthTolerance( opt - min );
268 data->SetOptGap( opt );
269 data->SetGapTolerance( opt - min );
282 auto data = std::make_shared<DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA>();
283 data->SetRuleName( aRule.
m_Name );
284 data->SetConstraintCode(
"text_height" );
305 auto data = std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>();
306 data->SetRuleName( aRule.
m_Name );
307 data->SetConstraintCode(
"track_width" );
314 data->SetOptWidth( opt );
315 data->SetWidthTolerance( opt - min );
328 auto data = std::make_shared<DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA>();
329 data->SetRuleName( aRule.
m_Name );
330 data->SetConstraintCode(
"length" );
336 auto convert = [&](
int aValue )
338 return timeDomain ?
toPS( aValue ) :
toMM( aValue );
347 data->SetTimeDomain( timeDomain );
348 data->SetOptimumLength( opt );
349 data->SetTolerance( ( max - min ) / 2.0 );
362 auto data = std::make_shared<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>();
363 data->SetRuleName( aRule.
m_Name );
364 data->SetConstraintCode(
"length" );
372 data->SetOptimumLength( optMM );
373 data->SetTolerance( ( maxMM - minMM ) / 2.0 );
389 auto data = std::make_shared<DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA>();
390 data->SetRuleName( aRule.
m_Name );
394 if( constraint && constraint->
m_Test )
398 data->SetTopLayerEnabled( expr.Contains( wxS(
"F.Cu" ) ) );
399 data->SetBottomLayerEnabled( expr.Contains( wxS(
"B.Cu" ) ) );
402 wxString remaining = expr;
403 remaining.Replace( wxS(
"A.Layer == 'F.Cu'" ), wxS(
"" ) );
404 remaining.Replace( wxS(
"A.Layer == 'B.Cu'" ), wxS(
"" ) );
406 if( remaining.Contains( wxS(
"A.Layer" ) ) )
409 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
410 customData->SetRuleName( aRule.
m_Name );
420 auto data = std::make_shared<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>();
421 data->SetRuleName( aRule.
m_Name );
422 data->SetConstraintCode( wxS(
"allowed_orientation" ) );
426 if( constraint && constraint->
m_Test )
430 data->SetIsZeroDegreesAllowed( expr.Contains( wxS(
"== 0 deg" ) ) );
431 data->SetIsNinetyDegreesAllowed( expr.Contains( wxS(
"== 90 deg" ) ) );
432 data->SetIsOneEightyDegreesAllowed( expr.Contains( wxS(
"== 180 deg" ) ) );
433 data->SetIsTwoSeventyDegreesAllowed( expr.Contains( wxS(
"== 270 deg" ) ) );
435 if( data->GetIsZeroDegreesAllowed() && data->GetIsNinetyDegreesAllowed()
436 && data->GetIsOneEightyDegreesAllowed() && data->GetIsTwoSeventyDegreesAllowed() )
438 data->SetIsAllDegreesAllowed(
true );
442 if( data->GetIsZeroDegreesAllowed() || data->GetIsNinetyDegreesAllowed()
443 || data->GetIsOneEightyDegreesAllowed() || data->GetIsTwoSeventyDegreesAllowed() )
450 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
451 customData->SetRuleName( aRule.
m_Name );
456 data->SetIsAllDegreesAllowed(
true );
464 auto data = std::make_shared<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>();
465 data->SetRuleName( aRule.
m_Name );
466 data->SetConstraintCode( wxS(
"disallow_via" ) );
483 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
484 data->SetRuleName( aRule.
m_Name );
494 data->SetRuleName( aRule.
m_Name );
497 data->SetConstraintCode( code );
507 data->SetNumericInputValue( constraint->
GetValue().
Max() );
509 data->SetNumericInputValue( constraint->
GetValue().
Max() / 1000.0 );
511 data->SetNumericInputValue( constraint->
GetValue().
Min() );
523 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
524 data->SetRuleName( aRule.
m_Name );
532 const wxString& aOriginalText )
534 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries;
543 bool fitsStructuredPanels =
true;
550 fitsStructuredPanels =
false;
556 std::vector<DRC_PANEL_MATCH> matches;
558 if( fitsStructuredPanels )
567 if( assertion && assertion->
m_Test )
571 if( expr.Contains( wxS(
"Orientation" ) ) && !expr.Contains( wxS(
"Layer" ) ) )
578 if( !condition.IsEmpty()
579 && ( condition.Contains( wxS(
"L == 'F.Mask'" ) ) || condition.Contains( wxS(
"L == 'B.Mask'" ) ) ) )
583 else if( !condition.IsEmpty() && !condition.Contains( wxS(
"L == 'F.SilkS'" ) )
584 && !condition.Contains( wxS(
"L == 'B.SilkS'" ) ) )
592 if( !constraintData )
597 auto customFallback = std::dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( constraintData );
599 if( customFallback && match.panelType !=
CUSTOM_RULE )
606 wxString cleanedCondition = condition;
609 bool hasBothSides = condition.Contains( wxS(
"L == 'F.Mask' || L == 'B.Mask'" ) );
614 constraintData->SetLayerSource( wxS(
"" ) );
616 cleanedCondition.Replace( wxS(
"L == 'F.Mask' || L == 'B.Mask'" ), wxS(
"" ) );
620 bool isFront = condition.Contains( wxS(
"F.Mask" ) );
622 constraintData->SetLayers( { layer } );
623 constraintData->SetLayerSource( isFront ? wxS(
"F.SilkS" ) : wxS(
"B.SilkS" ) );
625 cleanedCondition.Replace( wxS(
"L == 'F.Mask'" ), wxS(
"" ) );
626 cleanedCondition.Replace( wxS(
"L == 'B.Mask'" ), wxS(
"" ) );
634 wxString cleanedCondition = condition;
636 bool hasBothSides = condition.Contains( wxS(
"L == 'F.SilkS' || L == 'B.SilkS'" ) );
641 constraintData->SetLayerSource( wxS(
"" ) );
643 cleanedCondition.Replace( wxS(
"L == 'F.SilkS' || L == 'B.SilkS'" ), wxS(
"" ) );
645 else if( condition.Contains( wxS(
"L == 'F.SilkS'" ) ) || condition.Contains( wxS(
"L == 'B.SilkS'" ) ) )
647 bool isFront = condition.Contains( wxS(
"F.SilkS" ) );
649 constraintData->SetLayers( { layer } );
650 constraintData->SetLayerSource( isFront ? wxS(
"F.SilkS" ) : wxS(
"B.SilkS" ) );
652 cleanedCondition.Replace( wxS(
"L == 'F.SilkS'" ), wxS(
"" ) );
653 cleanedCondition.Replace( wxS(
"L == 'B.SilkS'" ), wxS(
"" ) );
661 wxString cleanedCondition = condition;
663 cleanedCondition.Replace( wxS(
"A.Pad_Type == 'SMD'" ), wxS(
"" ) );
664 cleanedCondition.Replace( wxS(
"B.Pad_Type == 'SMD'" ), wxS(
"" ) );
669 if( match.panelType ==
CUSTOM_RULE && customFallback )
676 constraintData->SetRuleCondition( condition );
683 if( source.StartsWith( wxS(
"'" ) ) && source.EndsWith( wxS(
"'" ) ) )
684 source = source.Mid( 1, source.Length() - 2 );
688 if( !comment.IsEmpty() )
689 constraintData->SetComment( comment );
692 if( entries.empty() )
695 entries.push_back( std::move( entry ) );
699 if( entries.empty() )
701 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>();
702 customData->SetRuleName( aRule.
m_Name );
703 customData->SetRuleCondition( condition );
706 if( !comment.IsEmpty() )
707 customData->SetComment( comment );
714 if( source.StartsWith( wxS(
"'" ) ) && source.EndsWith( wxS(
"'" ) ) )
715 source = source.Mid( 1, source.Length() - 2 );
718 entries.push_back( std::move( entry ) );
766 wxString quotedSearch = wxString::Format( wxS(
"(rule \"%s\"" ), aRuleName );
767 wxString unquotedSearch = wxString::Format( wxS(
"(rule %s" ), aRuleName );
769 size_t startPos = aContent.find( quotedSearch );
771 if( startPos == wxString::npos )
775 while( ( pos = aContent.find( unquotedSearch, pos ) ) != wxString::npos )
777 size_t afterMatch = pos + unquotedSearch.length();
779 if( afterMatch >= aContent.length()
780 || aContent[afterMatch] ==
')'
781 || aContent[afterMatch] ==
' '
782 || aContent[afterMatch] ==
'\n'
783 || aContent[afterMatch] ==
'\r'
784 || aContent[afterMatch] ==
'\t' )
794 if( startPos == wxString::npos )
795 return wxEmptyString;
799 size_t endPos = startPos;
800 bool inString =
false;
801 bool escaped =
false;
803 for(
size_t i = startPos; i < aContent.length(); ++i )
805 wxUniChar c = aContent[i];
821 inString = !inString;
836 if( parenCount == 0 )
844 if( parenCount != 0 )
845 return wxEmptyString;
847 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.