31#include <fmt/format.h>
35#include <wx/mstream.h>
36#include <wx/tokenzr.h>
72using namespace TSCHEMATIC_T;
77 unsigned aLineCount,
SCH_SHEET* aRootSheet,
79 SCHEMATIC_LEXER( aLineReader ),
80 m_requiredVersion( 0 ),
83 m_appending( aIsAppending ),
84 m_progressReporter( aProgressReporter ),
85 m_lineReader( aLineReader ),
86 m_lastProgressLine( 0 ),
87 m_lineCount( aLineCount ),
88 m_rootSheet( aRootSheet )
95 const unsigned PROGRESS_DELTA = 500;
117 KIID id( FromUTF8() );
134 else if( token == T_no )
137 Expecting(
"yes or no" );
148 bool ret = aDefaultValue;
150 if( PrevTok() == T_LEFT )
155 if(
static_cast<int>( token ) ==
DSN_RIGHT )
156 return aDefaultValue;
160 else if( token == T_no )
163 Expecting(
"yes or no" );
170 return aDefaultValue;
185 bool versionChecked =
false;
196 versionChecked =
true;
199 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
201 if( token != T_LEFT )
227 case T_generator_version:
247 aSymbolLibMap[symbol->
GetName()] = symbol;
252 Expecting(
"symbol, generator, or generator_version" );
266 if( CurTok() == T_LEFT )
270 if( CurTok() == T_symbol )
275 const std::vector<wxString>* embeddedFonts =
282 textItem->ResolveFont( embeddedFonts );
287 wxString msg = wxString::Format(
_(
"Cannot parse %s as a symbol" ),
288 GetTokenString( CurTok() ) );
299 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
300 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
306 wxString unitDisplayName;
308 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
310 symbol->SetUnitCount( 1 );
322 if( !IsSymbol( token ) )
324 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(),
333 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
340 if(
static_cast<int>(
name.size() ) > bad_pos )
342 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
351 CurLineNumber(), CurOffset() );
356 symbol->SetLibId(
id );
358 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
360 if( token != T_LEFT )
380 case T_exclude_from_sim:
381 symbol->SetExcludedFromSim(
parseBool() );
386 symbol->SetExcludedFromBOM( !
parseBool() );
391 symbol->SetExcludedFromBoard( !
parseBool() );
403 if( !IsSymbol( token ) )
406 CurLineNumber(), CurOffset() );
414 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
416 auto it = aSymbolLibMap.find(
name );
418 if( it == aSymbolLibMap.end() )
420 error.Printf(
_(
"No parent for extended symbol %s" ),
name.c_str() );
421 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
424 symbol->SetParent( it->second );
433 if( !IsSymbol( token ) )
436 CurLineNumber(), CurOffset() );
444 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
448 error.Printf(
_(
"Invalid symbol unit name prefix %s" ),
name.c_str() );
449 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
454 wxStringTokenizer tokenizer(
name,
"_" );
456 if( tokenizer.CountTokens() != 2 )
458 error.Printf(
_(
"Invalid symbol unit name suffix %s" ),
name.c_str() );
459 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
462 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
464 error.Printf(
_(
"Invalid symbol unit number %s" ),
name.c_str() );
465 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
468 m_unit =
static_cast<int>( tmp );
470 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
472 error.Printf(
_(
"Invalid symbol convert number %s" ),
name.c_str() );
473 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
479 symbol->SetHasAlternateBodyStyle(
true,
false );
481 if(
m_unit > symbol->GetUnitCount() )
482 symbol->SetUnitCount(
m_unit,
false );
484 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
486 if( token != T_LEFT )
496 if( IsSymbol( token ) )
498 unitDisplayName = FromUTF8();
499 symbol->SetUnitDisplayName(
m_unit, unitDisplayName );
515 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
518 symbol->AddDrawItem( item,
false );
522 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
541 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
544 symbol->AddDrawItem( item,
false );
547 case T_embedded_fonts:
549 symbol->SetAreFontsEmbedded(
parseBool() );
554 case T_embedded_files:
557 embeddedFilesParser.SyncLineReaderWith( *
this );
561 embeddedFilesParser.
ParseEmbedded( symbol->GetEmbeddedFiles() );
565 wxLogError( e.
What() );
568 SyncLineReaderWith( embeddedFilesParser );
573 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
574 "rectangle, or text" );
578 symbol->GetDrawItems().sort();
581 const std::vector<wxString>* embeddedFonts =
582 symbol->GetEmbeddedFiles()->UpdateFontFiles();
584 symbol->RunOnChildren(
588 textItem->ResolveFont( embeddedFonts );
591 return symbol.release();
607 default: Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
621 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
623 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
631 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
633 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
640 strokeParser.SyncLineReaderWith( *
this );
643 SyncLineReaderWith( strokeParser );
649 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
652 aFill.
m_Color = COLOR4D::UNSPECIFIED;
656 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
658 if( token != T_LEFT )
671 case T_none: aFill.
m_FillType = FILL_T::NO_FILL;
break;
672 case T_outline: aFill.
m_FillType = FILL_T::FILLED_SHAPE;
break;
673 case T_background: aFill.
m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR;
break;
674 case T_color: aFill.
m_FillType = FILL_T::FILLED_WITH_COLOR;
break;
675 default: Expecting(
"none, outline, color or background" );
696 Expecting(
"type or color" );
703 bool aEnforceMinTextSize )
705 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
706 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
723 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
725 if( token == T_LEFT )
731 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
733 if( token == T_LEFT )
784 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
791 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
800 case T_mirror:
break;
801 default: Expecting(
"left, right, top, bottom, or mirror" );
810 wxString hyperlink = FromUTF8();
815 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
834 Expecting(
"font, justify, hide or href" );
842 wxCHECK_RET( CurTok() == aHeaderType,
843 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
849 if( tok == T_version )
863 wxCHECK_RET( CurTok() == T_pin_names,
864 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
874 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
877 if( token == T_hide )
879 aSymbol->SetShowPinNames(
false );
883 if( token != T_LEFT )
898 aSymbol->SetShowPinNames( !
parseBool() );
903 Expecting(
"offset or hide" );
911 wxCHECK_RET( CurTok() == T_pin_numbers,
912 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_number token." );
921 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
924 if( token == T_hide )
926 aSymbol->SetShowPinNumbers(
false );
930 if( token != T_LEFT )
940 aSymbol->SetShowPinNumbers( !
parseBool() );
954 wxCHECK_MSG( CurTok() == T_property,
nullptr,
955 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
956 wxCHECK( aSymbol,
nullptr );
960 auto field = std::make_unique<SCH_FIELD>( aSymbol.get(),
MANDATORY_FIELDS );
964 field->SetVisible(
true );
968 if( token == T_private )
970 field->SetPrivate(
true );
974 if( !IsSymbol( token ) )
976 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
984 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
988 field->SetName(
name );
1003 if( !IsSymbol( token ) )
1005 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1012 field->SetText( value );
1014 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1016 if( token != T_LEFT )
1017 Expecting( T_LEFT );
1037 field->SetPosition(
parseXY(
true ) );
1049 field->SetNameShown( show );
1053 case T_do_not_autoplace:
1056 field->SetCanAutoplace( !doNotAutoplace );
1061 Expecting(
"id, at, show_name, do_not_autoplace, or effects" );
1069 int nextAvailableId = field->GetId() + 1;
1072 nextAvailableId += 1;
1074 field->SetId( nextAvailableId );
1079 if( field->IsMandatory() )
1081 existingField = aSymbol->GetFieldById( field->GetId() );
1083 *existingField = *field;
1085 return existingField;
1087 else if(
name ==
"ki_keywords" )
1090 aSymbol->SetKeyWords( value );
1094 else if(
name ==
"ki_description" )
1096 aSymbol->SetDescription( value );
1099 else if(
name ==
"ki_fp_filters" )
1102 wxArrayString filters;
1103 wxStringTokenizer tokenizer( value );
1105 while( tokenizer.HasMoreTokens() )
1107 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1108 filters.Add( curr_token );
1111 aSymbol->SetFPFilters( filters );
1114 else if(
name ==
"ki_locked" )
1118 aSymbol->LockUnits(
true );
1124 existingField = aSymbol->FindField( field->GetCanonicalName() );
1135 for(
int ii = 1; ii < 10 && existingField; ii++ )
1137 wxString newname = base_name;
1138 newname <<
'_' << ii;
1140 existingField = aSymbol->FindField( newname );
1142 if( !existingField )
1143 field->SetName( newname );
1147 if( !existingField )
1149 aSymbol->AddDrawItem( field.get(),
false );
1151 return field.release();
1164 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1165 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1171 bool hasMidPoint =
false;
1179 bool hasAngles =
false;
1181 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC,
LAYER_DEVICE );
1188 if( token == T_private )
1190 arc->SetPrivate(
true );
1194 for( ; token != T_RIGHT; token = NextTok() )
1196 if( token != T_LEFT )
1197 Expecting( T_LEFT );
1220 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1222 if( token != T_LEFT )
1223 Expecting( T_LEFT );
1251 Expecting(
"at, length, or angles" );
1259 arc->SetStroke( stroke );
1265 arc->SetFillColor( fill.
m_Color );
1269 Expecting(
"start, mid, end, radius, stroke, or fill" );
1275 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1286 EDA_ANGLE arc_start, arc_end, arc_angle;
1287 arc->CalcArcAngles( arc_start, arc_end );
1288 arc_angle = arc_end - arc_start;
1293 arc->SetStart( endPoint );
1294 arc->SetEnd( startPoint );
1297 arc->SetCenter( new_center );
1303 arc->SetCenter( new_center );
1307 else if( hasAngles )
1309 arc->SetCenter( center );
1315 arc->SetStart( endPoint );
1316 arc->SetEnd( startPoint );
1320 EDA_ANGLE arc_start, arc_end, arc_angle;
1321 arc->CalcArcAngles( arc_start, arc_end );
1322 arc_angle = arc_end - arc_start;
1328 arc->SetStart( startPoint );
1329 arc->SetEnd( endPoint );
1333 arc->SetStart( startPoint );
1334 arc->SetEnd( endPoint );
1337 arc->SetCenter( new_center );
1342 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1345 return arc.release();
1351 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1352 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1358 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER,
LAYER_DEVICE );
1360 bezier->SetUnit(
m_unit );
1365 if( token == T_private )
1367 bezier->SetPrivate(
true );
1371 for( ; token != T_RIGHT; token = NextTok() )
1373 if( token != T_LEFT )
1374 Expecting( T_LEFT );
1384 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1386 if( token != T_LEFT )
1387 Expecting( T_LEFT );
1396 case 0: bezier->SetStart(
parseXY(
true ) );
break;
1397 case 1: bezier->SetBezierC1(
parseXY(
true ) );
break;
1398 case 2: bezier->SetBezierC2(
parseXY(
true ) );
break;
1399 case 3: bezier->SetEnd(
parseXY(
true ) );
break;
1400 default: Unexpected(
"control point" );
break;
1410 bezier->SetStroke( stroke );
1416 bezier->SetFillColor( fill.
m_Color );
1420 Expecting(
"pts, stroke, or fill" );
1424 bezier->RebuildBezierToSegmentsPointsList( bezier->GetPenWidth() / 2 );
1426 return bezier.release();
1432 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1433 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1441 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE,
LAYER_DEVICE );
1443 circle->SetUnit(
m_unit );
1448 if( token == T_private )
1450 circle->SetPrivate(
true );
1454 for( ; token != T_RIGHT; token = NextTok() )
1456 if( token != T_LEFT )
1457 Expecting( T_LEFT );
1475 circle->SetStroke( stroke );
1481 circle->SetFillColor( fill.
m_Color );
1485 Expecting(
"center, radius, stroke, or fill" );
1489 circle->SetCenter( center );
1490 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
1492 return circle.release();
1503 case T_input:
return ELECTRICAL_PINTYPE::PT_INPUT;
1504 case T_output:
return ELECTRICAL_PINTYPE::PT_OUTPUT;
1505 case T_bidirectional:
return ELECTRICAL_PINTYPE::PT_BIDI;
1506 case T_tri_state:
return ELECTRICAL_PINTYPE::PT_TRISTATE;
1507 case T_passive:
return ELECTRICAL_PINTYPE::PT_PASSIVE;
1508 case T_unspecified:
return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1509 case T_power_in:
return ELECTRICAL_PINTYPE::PT_POWER_IN;
1510 case T_power_out:
return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1511 case T_open_collector:
return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1512 case T_open_emitter:
return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1514 case T_no_connect:
return ELECTRICAL_PINTYPE::PT_NC;
1515 case T_free:
return ELECTRICAL_PINTYPE::PT_NIC;
1518 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1519 "power_in, power_out, open_collector, open_emitter, free or "
1521 return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1530 case T_line:
return GRAPHIC_PINSHAPE::LINE;
1531 case T_inverted:
return GRAPHIC_PINSHAPE::INVERTED;
1532 case T_clock:
return GRAPHIC_PINSHAPE::CLOCK;
1533 case T_inverted_clock:
return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1534 case T_input_low:
return GRAPHIC_PINSHAPE::INPUT_LOW;
1535 case T_clock_low:
return GRAPHIC_PINSHAPE::CLOCK_LOW;
1536 case T_output_low:
return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1537 case T_edge_clock_high:
return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1538 case T_non_logic:
return GRAPHIC_PINSHAPE::NONLOGIC;
1541 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1542 "output_low, edge_clock_high, non_logic" );
1543 return GRAPHIC_PINSHAPE::LINE;
1547 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1548 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1553 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1560 pin->SetType( parseType( token ) );
1564 pin->SetShape( parseShape( token ) );
1566 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1569 if( token == T_hide )
1571 pin->SetVisible(
false );
1575 if( token != T_LEFT )
1576 Expecting( T_LEFT );
1585 switch(
parseInt(
"pin orientation" ) )
1587 case 0:
pin->SetOrientation( PIN_ORIENTATION::PIN_RIGHT );
break;
1588 case 90:
pin->SetOrientation( PIN_ORIENTATION::PIN_UP );
break;
1589 case 180:
pin->SetOrientation( PIN_ORIENTATION::PIN_LEFT );
break;
1590 case 270:
pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN );
break;
1591 default: Expecting(
"0, 90, 180, or 270" );
1610 if( !IsSymbol( token ) )
1619 pin->SetName( FromUTF8() );
1623 if( token != T_RIGHT )
1627 if( token == T_effects )
1634 pin->SetNameTextSize(
text.GetTextHeight() );
1639 Expecting(
"effects" );
1648 if( !IsSymbol( token ) )
1651 CurLineNumber(), CurOffset() );
1654 pin->SetNumber( FromUTF8() );
1657 if( token != T_RIGHT )
1661 if( token == T_effects )
1668 pin->SetNumberTextSize(
text.GetTextHeight() );
1673 Expecting(
"effects" );
1685 if( !IsSymbol( token ) )
1688 CurLineNumber(), CurOffset() );
1694 alt.
m_Type = parseType( token );
1697 alt.
m_Shape = parseShape( token );
1699 pin->GetAlternates()[ alt.
m_Name ] = alt;
1706 Expecting(
"at, name, number, hide, length, or alternate" );
1710 return pin.release();
1716 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1717 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1722 std::unique_ptr<SCH_SHAPE> poly = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_DEVICE );
1729 if( token == T_private )
1731 poly->SetPrivate(
true );
1735 for( ; token != T_RIGHT; token = NextTok() )
1737 if( token != T_LEFT )
1738 Expecting( T_LEFT );
1745 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1747 if( token != T_LEFT )
1748 Expecting( T_LEFT );
1755 poly->AddPoint(
parseXY(
true ) );
1764 poly->SetStroke( stroke );
1770 poly->SetFillColor( fill.
m_Color );
1774 Expecting(
"pts, stroke, or fill" );
1778 return poly.release();
1784 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1785 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1790 auto rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE,
LAYER_DEVICE );
1792 rectangle->SetUnit(
m_unit );
1797 if( token == T_private )
1799 rectangle->SetPrivate(
true );
1803 for( ; token != T_RIGHT; token = NextTok() )
1805 if( token != T_LEFT )
1806 Expecting( T_LEFT );
1813 rectangle->SetPosition(
parseXY(
true ) );
1818 rectangle->SetEnd(
parseXY(
true ) );
1824 rectangle->SetStroke( stroke );
1830 rectangle->SetFillColor( fill.
m_Color );
1834 Expecting(
"start, end, stroke, or fill" );
1838 return rectangle.release();
1844 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1845 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1848 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1855 if( token == T_private )
1857 text->SetPrivate(
true );
1861 if( !IsSymbol( token ) )
1863 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1867 text->SetText( FromUTF8() );
1869 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1871 if( token != T_LEFT )
1872 Expecting( T_LEFT );
1890 Expecting(
"at or effects" );
1894 return text.release();
1900 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
1901 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
1913 bool foundEnd =
false;
1914 bool foundSize =
false;
1915 bool foundMargins =
false;
1917 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
1919 textBox->SetUnit(
m_unit );
1923 if( token == T_private )
1925 textBox->SetPrivate(
true );
1929 if( !IsSymbol( token ) )
1931 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1935 textBox->SetText( FromUTF8() );
1937 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1939 if( token != T_LEFT )
1940 Expecting( T_LEFT );
1971 textBox->SetStroke( stroke );
1977 textBox->SetFillColor( fill.
m_Color );
1982 textBox->SetMarginLeft(
left );
1983 textBox->SetMarginTop( top );
1984 textBox->SetMarginRight(
right );
1985 textBox->SetMarginBottom( bottom );
1986 foundMargins =
true;
1995 Expecting(
"at, size, stroke, fill or effects" );
1999 textBox->SetPosition( pos );
2002 textBox->SetEnd( end );
2003 else if( foundSize )
2004 textBox->SetEnd( pos + size );
2006 Expecting(
"size" );
2010 int margin = textBox->GetLegacyTextMargin();
2011 textBox->SetMarginLeft( margin );
2012 textBox->SetMarginTop( margin );
2013 textBox->SetMarginRight( margin );
2014 textBox->SetMarginBottom( margin );
2017 return textBox.release();
2023 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
2024 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
2030 wxString pageType = FromUTF8();
2032 if( !aPageInfo.
SetType( pageType ) )
2034 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
2061 if( token == T_portrait )
2066 else if( token != T_RIGHT )
2068 Expecting(
"portrait" );
2075 wxCHECK_RET( CurTok() == T_title_block,
2076 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
2080 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2082 if( token != T_LEFT )
2083 Expecting( T_LEFT );
2091 aTitleBlock.
SetTitle( FromUTF8() );
2096 aTitleBlock.
SetDate( FromUTF8() );
2111 int commentNumber =
parseInt(
"comment" );
2113 switch( commentNumber )
2162 CurLine(), CurLineNumber(), CurOffset() );
2169 Expecting(
"title, date, rev, company, or comment" );
2179 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2180 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2182 bool is_private =
false;
2184 T token = NextTok();
2186 if( token == T_private )
2192 if( !IsSymbol( token ) )
2194 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2198 wxString
name = FromUTF8();
2200 if(
name.IsEmpty() )
2202 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2208 if( !IsSymbol( token ) )
2210 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2215 wxString value = FromUTF8();
2217 int mandatoryFieldCount = 0;
2224 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>(
VECTOR2I( -1, -1 ),
2225 mandatoryFieldCount,
2227 field->SetText( value );
2228 field->SetVisible(
true );
2229 field->SetPrivate( is_private );
2240 field->SetPrivate(
false );
2252 field->SetPrivate(
false );
2256 else if( !
name.CmpNoCase( wxT(
"Sheet name" ) ) )
2261 else if( !
name.CmpNoCase( wxT(
"Sheet file" ) ) )
2269 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2271 if( token != T_LEFT )
2272 Expecting( T_LEFT );
2283 if(
id >= mandatoryFieldCount )
2290 field->SetPosition(
parseXY() );
2302 field->SetNameShown( show );
2306 case T_do_not_autoplace:
2309 field->SetCanAutoplace( !doNotAutoplace );
2314 Expecting(
"id, at, show_name, do_not_autoplace or effects" );
2318 return field.release();
2324 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2325 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2326 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2328 T token = NextTok();
2330 if( !IsSymbol( token ) )
2332 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2336 wxString
name = FromUTF8();
2338 if(
name.IsEmpty() )
2340 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2344 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2350 case T_input: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
2351 case T_output: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
2352 case T_bidirectional: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
2353 case T_tri_state: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
2354 case T_passive: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
2356 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2359 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2361 if( token != T_LEFT )
2362 Expecting( T_LEFT );
2370 sheetPin->SetPosition(
parseXY() );
2372 double angle =
parseDouble(
"sheet pin angle (side)" );
2375 sheetPin->SetSide( SHEET_SIDE::RIGHT );
2376 else if( angle == 90.0 )
2377 sheetPin->SetSide( SHEET_SIDE::TOP );
2378 else if( angle == 180.0 )
2379 sheetPin->SetSide( SHEET_SIDE::LEFT );
2380 else if( angle == 270.0 )
2381 sheetPin->SetSide( SHEET_SIDE::BOTTOM );
2383 Expecting(
"0, 90, 180, or 270" );
2400 Expecting(
"at, uuid or effects" );
2404 return sheetPin.release();
2410 wxCHECK_RET( CurTok() == T_sheet_instances,
2411 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2412 wxCHECK( aScreen, );
2416 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2418 if( token != T_LEFT )
2419 Expecting( T_LEFT );
2437 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2439 if( token != T_LEFT )
2440 Expecting( T_LEFT );
2444 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2447 size_t numReplacements = 0;
2465 for(
const wxString& ch : whitespaces )
2466 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2471 if( numReplacements > 0 )
2478 Expecting(
"path or page" );
2483 && ( instance.
m_Path.empty() ) )
2499 Expecting(
"path" );
2507 wxCHECK_RET( CurTok() == T_symbol_instances,
2508 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2509 wxCHECK( aScreen, );
2514 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2516 if( token != T_LEFT )
2517 Expecting( T_LEFT );
2534 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2536 if( token != T_LEFT )
2537 Expecting( T_LEFT );
2556 instance.
m_Value = FromUTF8();
2567 Expecting(
"path, unit, value or footprint" );
2576 Expecting(
"path" );
2585 wxCHECK( aSheet !=
nullptr, );
2589 wxCHECK( screen !=
nullptr, );
2591 if( aIsCopyableOnly )
2594 bool fileHasUuid =
false;
2608 if( !aIsCopyableOnly )
2613 if( CurTok() != T_kicad_sch )
2614 Expecting(
"kicad_sch" );
2630 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2632 if( aIsCopyableOnly && token == T_EOF )
2635 if( token != T_LEFT )
2636 Expecting( T_LEFT );
2666 case T_generator_version:
2692 if( aIsCopyableOnly )
2693 Unexpected( T_paper );
2703 if( aIsCopyableOnly )
2704 Unexpected( T_page );
2708 NeedSYMBOLorNUMBER();
2709 NeedSYMBOLorNUMBER();
2716 if( aIsCopyableOnly )
2717 Unexpected( T_title_block );
2731 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2733 if( token != T_LEFT )
2734 Expecting( T_LEFT );
2747 Expecting(
"symbol" );
2848 case T_netclass_flag:
2853 case T_global_label:
2854 case T_hierarchical_label:
2855 case T_directive_label:
2867 case T_sheet_instances:
2871 case T_symbol_instances:
2876 if( aIsCopyableOnly )
2877 Unexpected( T_bus_alias );
2882 case T_embedded_fonts:
2888 CurLineNumber(), CurOffset() );
2895 case T_embedded_files:
2901 CurLineNumber(), CurOffset() );
2904 embeddedFilesParser.SyncLineReaderWith( *
this );
2912 wxLogError( e.
What() );
2915 SyncLineReaderWith( embeddedFilesParser );
2921 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
2922 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
2923 "sheet, symbol, symbol_instances, text, title_block" );
2942 CurLineNumber(), CurOffset() );
2946 std::vector<std::string> fontNames;
2947 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
2957 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
2958 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
2963 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
2965 std::set<int> fieldIDsRead;
2978 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2980 if( token != T_LEFT )
2981 Expecting( T_LEFT );
2993 if( !IsSymbol( token ) )
2996 CurLineNumber(), CurOffset() );
2999 libName = FromUTF8();
3003 libName.Replace(
"{slash}",
"/" );
3013 if( !IsSymbol( token ) && token != T_NUMBER )
3014 Expecting(
"symbol|number" );
3017 wxString
name = FromUTF8();
3021 name.Replace(
"{slash}",
"/" );
3027 if(
static_cast<int>(
name.size() ) > bad_pos )
3029 wxString msg = wxString::Format(
3030 _(
"Symbol %s contains invalid character '%c'" ),
name,
3037 CurLineNumber(), CurOffset() );
3040 symbol->SetLibId( libId );
3046 symbol->SetPosition(
parseXY() );
3048 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
3051 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
3052 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
3053 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
3054 default: Expecting(
"0, 90, 180, or 270" );
3057 symbol->SetTransform( transform );
3066 else if( token == T_y )
3069 Expecting(
"x or y" );
3075 symbol->SetUnit(
parseInt(
"symbol unit" ) );
3082 symbol->SetBodyStyleUnconditional(
parseInt(
"symbol body style" ) );
3086 case T_exclude_from_sim:
3087 symbol->SetExcludedFromSim(
parseBool() );
3092 symbol->SetExcludedFromBOM( !
parseBool() );
3097 symbol->SetExcludedFromBoard( !
parseBool() );
3106 case T_fields_autoplaced:
3118 case T_default_instance:
3122 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3124 if( token != T_LEFT )
3125 Expecting( T_LEFT );
3144 symbol->SetValueFieldText( FromUTF8() );
3150 symbol->SetFootprintFieldText( FromUTF8() );
3155 Expecting(
"reference, unit, value or footprint" );
3164 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3166 if( token != T_LEFT )
3167 Expecting( T_LEFT );
3171 if( token != T_project )
3172 Expecting(
"project" );
3176 wxString projectName = FromUTF8();
3178 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3180 if( token != T_LEFT )
3181 Expecting( T_LEFT );
3185 if( token != T_path )
3186 Expecting(
"path" );
3195 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3197 if( token != T_LEFT )
3198 Expecting( T_LEFT );
3217 symbol->SetValueFieldText( FromUTF8() );
3223 symbol->SetFootprintFieldText( FromUTF8() );
3228 Expecting(
"reference, unit, value or footprint" );
3231 symbol->AddHierarchicalReference( instance );
3248 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3255 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3261 int nextAvailableId = field->
GetId() + 1;
3264 nextAvailableId += 1;
3266 field->
SetId( nextAvailableId );
3269 if( symbol->GetFieldById( field->
GetId() ) )
3270 *symbol->GetFieldById( field->
GetId() ) = *field;
3272 symbol->AddField( *field );
3275 symbol->UpdatePrefix();
3290 number = FromUTF8();
3292 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3294 if( token != T_LEFT )
3295 Expecting( T_LEFT );
3319 Expecting(
"alternate or uuid" );
3323 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3329 Expecting(
"lib_id, lib_name, at, mirror, uuid, on_board, in_bom, dnp, "
3330 "default_instance, property, pin, or instances" );
3334 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3335 symbol->SetSchSymbolLibraryName( libName );
3338 symbol->ClearFlags();
3340 return symbol.release();
3346 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3347 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3350 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3353 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3355 if( token != T_LEFT )
3356 Expecting( T_LEFT );
3363 bitmap->SetPosition(
parseXY() );
3389 data.reserve( 1 << 17 );
3391 while( token != T_RIGHT )
3393 if( !IsSymbol( token ) )
3394 Expecting(
"base64 image data" );
3400 wxMemoryBuffer buffer = wxBase64Decode( data );
3409 Expecting(
"at, scale, uuid or data" );
3422 return bitmap.release();
3428 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3429 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3435 std::vector<SCH_FIELD> fields;
3436 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3437 std::set<int> fieldIDsRead;
3442 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3444 if( token != T_LEFT )
3445 Expecting( T_LEFT );
3452 sheet->SetPosition(
parseXY() );
3461 sheet->SetSize( size );
3466 case T_exclude_from_sim:
3467 sheet->SetExcludedFromSim(
parseBool() );
3472 sheet->SetExcludedFromBOM( !
parseBool() );
3477 sheet->SetExcludedFromBoard( !
parseBool() );
3486 case T_fields_autoplaced:
3494 sheet->SetBorderWidth( stroke.
GetWidth() );
3495 sheet->SetBorderColor( stroke.
GetColor() );
3500 sheet->SetBackgroundColor( fill.
m_Color );
3517 if( fields.empty() )
3531 if( field->
GetId() < 0 )
3534 while( !fieldIDsRead.insert( field->
GetId() ).second )
3537 fields.emplace_back( *field );
3548 std::vector<SCH_SHEET_INSTANCE> instances;
3550 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3552 if( token != T_LEFT )
3553 Expecting( T_LEFT );
3557 if( token != T_project )
3558 Expecting(
"project" );
3562 wxString projectName = FromUTF8();
3564 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3566 if( token != T_LEFT )
3567 Expecting( T_LEFT );
3571 if( token != T_path )
3572 Expecting(
"path" );
3581 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3583 if( token != T_LEFT )
3584 Expecting( T_LEFT );
3604 static std::vector<wxString> whitespaces =
3610 for( wxString ch : whitespaces )
3619 Expecting(
"page" );
3623 instances.emplace_back( instance );
3627 sheet->setInstances( instances );
3632 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3636 sheet->SetFields( fields );
3638 return sheet.release();
3644 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3645 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3648 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3650 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3652 if( token != T_LEFT )
3653 Expecting( T_LEFT );
3660 junction->SetPosition(
parseXY() );
3678 junction->SetColor(
color );
3690 Expecting(
"at, diameter, color or uuid" );
3694 return junction.release();
3700 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3701 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3704 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3706 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3708 if( token != T_LEFT )
3709 Expecting( T_LEFT );
3716 no_connect->SetPosition(
parseXY() );
3727 Expecting(
"at or uuid" );
3731 return no_connect.release();
3737 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3738 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3742 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3744 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3746 if( token != T_LEFT )
3747 Expecting( T_LEFT );
3754 busEntry->SetPosition(
parseXY() );
3764 busEntry->SetSize( size );
3771 busEntry->SetStroke( stroke );
3781 Expecting(
"at, size, uuid or stroke" );
3785 return busEntry.release();
3805 std::unique_ptr<SCH_SHAPE> polyline = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_NOTES );
3807 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3809 if( token != T_LEFT )
3810 Expecting( T_LEFT );
3817 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3819 if( token != T_LEFT )
3820 Expecting( T_LEFT );
3827 polyline->AddPoint(
parseXY() );
3840 polyline->SetStroke( stroke );
3846 polyline->SetFillColor( fill.
m_Color );
3857 Expecting(
"pts, uuid, stroke, or fill" );
3861 return polyline.release();
3880 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
3883 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
3885 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3887 if( token != T_LEFT )
3888 Expecting( T_LEFT );
3901 line->SetStartPoint(
parseXY() );
3909 line->SetEndPoint(
parseXY() );
3916 line->SetStroke( stroke );
3926 Expecting(
"at, uuid or stroke" );
3930 return line.release();
3936 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
3937 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
3945 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
3947 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3949 if( token != T_LEFT )
3950 Expecting( T_LEFT );
3973 arc->SetStroke( stroke );
3979 arc->SetFillColor( fill.
m_Color );
3985 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
3990 Expecting(
"start, mid, end, stroke, fill or uuid" );
3994 arc->SetArcGeometry( startPoint, midPoint, endPoint );
3996 return arc.release();
4002 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
4003 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
4010 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
4012 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4014 if( token != T_LEFT )
4015 Expecting( T_LEFT );
4033 circle->SetStroke( stroke );
4039 circle->SetFillColor( fill.
m_Color );
4045 const_cast<KIID&
>( circle->m_Uuid ) =
KIID( FromUTF8() );
4050 Expecting(
"center, radius, stroke, fill or uuid" );
4054 circle->SetCenter( center );
4055 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
4057 return circle.release();
4063 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4064 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4069 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
4071 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4073 if( token != T_LEFT )
4074 Expecting( T_LEFT );
4081 rectangle->SetPosition(
parseXY() );
4086 rectangle->SetEnd(
parseXY() );
4092 rectangle->SetStroke( stroke );
4098 rectangle->SetFillColor( fill.
m_Color );
4104 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4109 Expecting(
"start, end, stroke, fill or uuid" );
4113 return rectangle.release();
4119 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4120 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4125 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4127 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4129 if( token != T_LEFT )
4130 Expecting( T_LEFT );
4144 ruleArea->SetPolyShape( sch_rule_poly );
4146 ruleArea->SetStroke( poly->GetStroke() );
4147 ruleArea->SetFillMode( poly->GetFillMode() );
4148 ruleArea->SetFillColor( poly->GetFillColor() );
4152 Expecting(
"polyline" );
4156 return ruleArea.release();
4162 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4163 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4168 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
4170 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4172 if( token != T_LEFT )
4173 Expecting( T_LEFT );
4183 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4185 if( token != T_LEFT )
4186 Expecting( T_LEFT );
4195 case 0: bezier->SetStart(
parseXY() );
break;
4196 case 1: bezier->SetBezierC1(
parseXY() );
break;
4197 case 2: bezier->SetBezierC2(
parseXY() );
break;
4198 case 3: bezier->SetEnd(
parseXY() );
break;
4199 default: Unexpected(
"control point" );
break;
4209 bezier->SetStroke( stroke );
4215 bezier->SetFillColor( fill.
m_Color );
4221 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4226 Expecting(
"pts, stroke, fill or uuid" );
4230 bezier->RebuildBezierToSegmentsPointsList( bezier->GetPenWidth() / 2 );
4232 return bezier.release();
4239 std::unique_ptr<SCH_TEXT>
text;
4243 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4244 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4245 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4246 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4247 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4248 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4250 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4258 text->SetText( FromUTF8() );
4260 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4262 if( token != T_LEFT )
4263 Expecting( T_LEFT );
4269 case T_exclude_from_sim:
4280 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4296 Unexpected( T_shape );
4304 case T_input: label->
SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
4305 case T_output: label->
SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
4306 case T_bidirectional: label->
SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
4307 case T_tri_state: label->
SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
4308 case T_passive: label->
SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
4309 case T_dot: label->
SetShape( LABEL_FLAG_SHAPE::F_DOT );
break;
4310 case T_round: label->
SetShape( LABEL_FLAG_SHAPE::F_ROUND );
break;
4311 case T_diamond: label->
SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
break;
4312 case T_rectangle: label->
SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
break;
4314 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4325 Unexpected( T_length );
4334 case T_fields_autoplaced:
4366 Unexpected( T_property );
4393 Expecting(
"at, shape, iref, uuid or effects" );
4399 if( label && label->
GetFields().empty() )
4402 return text.release();
4408 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4409 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4411 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4415 return textBox.release();
4421 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4422 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4424 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4428 return cell.release();
4444 bool foundEnd =
false;
4445 bool foundSize =
false;
4446 bool foundMargins =
false;
4450 aTextBox->
SetText( FromUTF8() );
4452 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4454 if( token != T_LEFT )
4455 Expecting( T_LEFT );
4461 case T_exclude_from_sim:
4492 cell->SetColSpan(
parseInt(
"column span" ) );
4493 cell->SetRowSpan(
parseInt(
"row span" ) );
4497 Expecting(
"at, size, stroke, fill, effects or uuid" );
4521 foundMargins =
true;
4537 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4539 Expecting(
"at, size, stroke, fill, effects or uuid" );
4547 else if( foundSize )
4548 aTextBox->
SetEnd( pos + size );
4550 Expecting(
"size" );
4565 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4566 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4570 STROKE_PARAMS borderStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4571 STROKE_PARAMS separatorsStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4572 std::unique_ptr<SCH_TABLE> table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4574 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4576 if( token != T_LEFT )
4577 Expecting( T_LEFT );
4583 case T_column_count:
4584 table->SetColCount(
parseInt(
"column count" ) );
4588 case T_column_widths:
4592 while( ( token = NextTok() ) != T_RIGHT )
4602 while( ( token = NextTok() ) != T_RIGHT )
4609 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4611 if( token != T_LEFT )
4612 Expecting( T_LEFT );
4616 if( token != T_table_cell )
4617 Expecting(
"table_cell" );
4625 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4627 if( token != T_LEFT )
4628 Expecting( T_LEFT );
4635 table->SetStrokeExternal(
parseBool() );
4646 table->SetBorderStroke( borderStroke );
4650 Expecting(
"external, header or stroke" );
4658 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4660 if( token != T_LEFT )
4661 Expecting( T_LEFT );
4679 table->SetSeparatorsStroke( separatorsStroke );
4683 Expecting(
"rows, cols, or stroke" );
4691 Expecting(
"columns, col_widths, row_heights, border, separators, header or cells" );
4695 return table.release();
4701 wxCHECK_RET( CurTok() == T_bus_alias,
4702 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4703 wxCHECK( aScreen, );
4706 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
4717 busAlias->SetName( alias );
4722 if( token != T_members )
4723 Expecting(
"members" );
4727 while( token != T_RIGHT )
4729 if( !IsSymbol( token ) )
4730 Expecting(
"quoted string" );
4732 member = FromUTF8();
4737 busAlias->Members().emplace_back( member );
constexpr EDA_IU_SCALE schIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
void SetContentModified(bool aModified=true)
KICAD_T Type() const
Returns the type of object.
virtual void SetParent(EDA_ITEM *aParent)
FILL_T GetFillMode() const
SHAPE_POLY_SET & GetPolyShape()
void SetFillColor(const COLOR4D &aColor)
int GetPointCount() const
void SetEnd(const VECTOR2I &aEnd)
void SetFillMode(FILL_T aFill)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
void SetTextColor(const COLOR4D &aColor)
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetUnresolvedFontName(const wxString &aFontName)
virtual const wxString & GetText() const
Return the string associated with the text object.
void SetTextPos(const VECTOR2I &aPoint)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
void SetBoldFlag(bool aBold)
Set only the italic flag, without changing the font.
virtual void SetVisible(bool aVisible)
void SetLineSpacing(double aLineSpacing)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
static bool ValidateHyperlink(const wxString &aURL)
Check if aURL is a valid hyperlink.
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
void SetHyperlink(wxString aLink)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
void ParseEmbedded(EMBEDDED_FILES *aFiles)
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
const std::vector< wxString > * GetFontFiles() const
If we just need the cached version of the font files, we can use this function which is const and wil...
void SetAreFontsEmbedded(bool aEmbedFonts)
Simple container to manage fill parameters.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Define a library symbol object.
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction) override
wxString GetName() const override
int UpdateFieldOrdinals()
Order optional field indices.
EMBEDDED_FILES * GetEmbeddedFiles() override
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
static const wxChar Custom[]
"User" defined page type
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
const BITMAP_BASE & GetImage() const
Get the underlying image.
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
Holds all the data relating to one schematic.
EMBEDDED_FILES * GetEmbeddedFiles() override
Object to handle a bitmap image that can be inserted in a schematic.
Class for a wire to bus entry.
void SetPinLength(int aLength)
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
const wxString & GetInternalName()
Get the initial name of the field set at creation (or set by SetName()).
SCH_ITEM * ParseSymbolDrawItem()
SCH_SHAPE * parseSymbolPolyLine()
SCH_TABLE * parseSchTable()
bool m_appending
Appending load status.
unsigned m_lastProgressLine
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
SCH_SHAPE * parseSchCircle()
SCH_TEXT * parseSchText()
SCH_TABLECELL * parseSchTableCell()
void parseSchSymbolInstances(SCH_SCREEN *aScreen)
void parsePinNumbers(std::unique_ptr< LIB_SYMBOL > &aSymbol)
LIB_SYMBOL * parseLibSymbol(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_RULE_AREA * parseSchRuleArea()
PROGRESS_REPORTER * m_progressReporter
void parseFill(FILL_PARAMS &aFill)
SCH_TEXTBOX * parseSymbolTextBox()
void parseBusAlias(SCH_SCREEN *aScreen)
std::set< int > m_fieldIDsRead
Field IDs that have been read so far for the current symbol.
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.
int m_unit
The current unit being parsed.
SCH_SHAPE * parseSymbolBezier()
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax, bool aEnforceMinTextSize=true)
SCH_TEXTBOX * parseSchTextBox()
SCH_SHEET * m_rootSheet
The rootsheet for full project loads or null for importing a schematic.
SCH_SHAPE * parseSchArc()
SCH_SHAPE * parseSchPolyLine()
SCH_BITMAP * parseImage()
SCH_SHAPE * parseSymbolCircle()
wxString m_generatorVersion
void ParseLib(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_PIN * parseSymbolPin()
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
wxString m_symbolName
The current symbol name.
VECTOR2I parseXY(bool aInvertY=false)
SCH_SHAPE * parseSymbolRectangle()
void parsePinNames(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SHAPE * parseSchBezier()
SCH_JUNCTION * parseJunction()
void ParseSchematic(SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Parse the internal LINE_READER object into aSheet.
SCH_SHEET_PIN * parseSchSheetPin(SCH_SHEET *aSheet)
int m_bodyStyle
The current body style being parsed.
SCH_NO_CONNECT * parseNoConnect()
SCH_TEXT * parseSymbolText()
SCH_SHAPE * parseSymbolArc()
SCH_BUS_WIRE_ENTRY * parseBusEntry()
SCH_SHAPE * parseSchRectangle()
SCH_FIELD * parseProperty(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SYMBOL * parseSchematicSymbol()
void parseSchTextBoxContent(SCH_TEXTBOX *aTextBox)
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
void parsePAGE_INFO(PAGE_INFO &aPageInfo)
int m_requiredVersion
Set to the symbol library file version required.
const LINE_READER * m_lineReader
LIB_SYMBOL * ParseSymbol(LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
Parse internal LINE_READER object into symbols and return all found.
void parseSchSheetInstances(SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
SCH_IO_KICAD_SEXPR_PARSER(LINE_READER *aLineReader=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, unsigned aLineCount=0, SCH_SHEET *aRootSheet=nullptr, bool aIsAppending=false)
Base class for any item which can be embedded within the SCHEMATIC container class,...
void SetFieldsAutoplaced(AUTOPLACE_ALGO aAlgo)
void SetShape(LABEL_FLAG_SHAPE aShape)
std::vector< SCH_FIELD > & GetFields()
Segment description base class to describe items which have 2 end points (track, wire,...
void SetStartPoint(const VECTOR2I &aPosition)
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
void SetEndPoint(const VECTOR2I &aPosition)
void SetFileFormatVersionAtLoad(int aVersion)
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).
void SetPageSettings(const PAGE_INFO &aPageSettings)
const KIID & GetUuid() const
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
SCHEMATIC * Schematic() const
void FixupEmbeddedData()
After loading a file from disk, the library symbols do not yet contain the full data for their embedd...
int GetFileFormatVersionAtLoad() const
KIID m_uuid
A unique identifier for each schematic file.
std::vector< SCH_SYMBOL_INSTANCE > m_symbolInstances
The list of symbol instances loaded from the schematic file.
void SetPosition(const VECTOR2I &aPos) override
void SetStroke(const STROKE_PARAMS &aStroke) override
STROKE_PARAMS GetStroke() const override
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslated=true)
SCH_SCREEN * GetScreen() const
void SetMarginBottom(int aBottom)
int GetLegacyTextMargin() const
void SetMarginLeft(int aLeft)
void SetMarginRight(int aRight)
void SetMarginTop(int aTop)
void SetExcludedFromSim(bool aExclude) override
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void ParseStroke(STROKE_PARAMS &aStroke)
Simple container to manage line stroke parameters.
void SetLineStyle(LINE_STYLE aLineStyle)
LINE_STYLE GetLineStyle() const
KIGFX::COLOR4D GetColor() const
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_360
static constexpr EDA_ANGLE ANGLE_180
@ FILLED_SHAPE
Fill with object color.
FONTCONFIG * Fontconfig()
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
#define MAX_PAGE_SIZE_EESCHEMA_MM
#define MIN_PAGE_SIZE_MM
Min and max page sizes for clamping, in mm.
PGM_BASE & Pgm()
The global program "get" accessor.
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
double parseDouble(LINE_READER &aReader, const char *aLine, const char **aOutput)
Parses an ASCII point string with possible leading whitespace into a double precision floating point ...
void fixupSchFillMode(SCH_SHAPE *aShape)
@ SHEET_MANDATORY_FIELDS
The first 2 are mandatory, and must be instantiated in SCH_SHEET.
#define SIM_LEGACY_ENABLE_FIELD
#define SIM_LEGACY_ENABLE_FIELD_V7
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString UnescapeString(const wxString &aSource)
constexpr int MilsToIU(int mils) const
A filename or source description, a problem input line, a line number, a byte offset,...
ELECTRICAL_PINTYPE m_Type
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
std::map< wxString, LIB_SYMBOL *, LibSymbolMapSort > LIB_SYMBOL_MAP
wxString GetCanonicalFieldName(int idx)
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ MANDATORY_FIELDS
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
VECTOR2< int32_t > VECTOR2I