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(), aSymbol->GetNextAvailableFieldId() );
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 );
996 field->SetId( fieldId );
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 );
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 nextFieldId = 0;
2224 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>(
VECTOR2I( -1, -1 ), nextFieldId,
2226 field->SetText( value );
2227 field->SetVisible(
true );
2228 field->SetPrivate( is_private );
2238 field->SetId( fieldId );
2239 field->SetPrivate(
false );
2250 field->SetId( fieldId );
2251 field->SetPrivate(
false );
2257 if(
name.CmpNoCase( wxT(
"Sheet name" ) ) == 0 )
2259 else if(
name.CmpNoCase( wxT(
"Sheet file" ) ) == 0 )
2263 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2265 if( token != T_LEFT )
2266 Expecting( T_LEFT );
2278 if(
id >= nextFieldId )
2286 field->SetPosition(
parseXY() );
2298 field->SetNameShown( show );
2302 case T_do_not_autoplace:
2305 field->SetCanAutoplace( !doNotAutoplace );
2310 Expecting(
"id, at, show_name, do_not_autoplace or effects" );
2314 return field.release();
2320 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2321 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2322 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2324 T token = NextTok();
2326 if( !IsSymbol( token ) )
2328 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2332 wxString
name = FromUTF8();
2334 if(
name.IsEmpty() )
2336 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2340 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2346 case T_input: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
2347 case T_output: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
2348 case T_bidirectional: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
2349 case T_tri_state: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
2350 case T_passive: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
2352 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2355 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2357 if( token != T_LEFT )
2358 Expecting( T_LEFT );
2366 sheetPin->SetPosition(
parseXY() );
2368 double angle =
parseDouble(
"sheet pin angle (side)" );
2371 sheetPin->SetSide( SHEET_SIDE::RIGHT );
2372 else if( angle == 90.0 )
2373 sheetPin->SetSide( SHEET_SIDE::TOP );
2374 else if( angle == 180.0 )
2375 sheetPin->SetSide( SHEET_SIDE::LEFT );
2376 else if( angle == 270.0 )
2377 sheetPin->SetSide( SHEET_SIDE::BOTTOM );
2379 Expecting(
"0, 90, 180, or 270" );
2396 Expecting(
"at, uuid or effects" );
2400 return sheetPin.release();
2406 wxCHECK_RET( CurTok() == T_sheet_instances,
2407 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2408 wxCHECK( aScreen, );
2412 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2414 if( token != T_LEFT )
2415 Expecting( T_LEFT );
2433 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2435 if( token != T_LEFT )
2436 Expecting( T_LEFT );
2440 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2443 size_t numReplacements = 0;
2461 for(
const wxString& ch : whitespaces )
2462 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2467 if( numReplacements > 0 )
2474 Expecting(
"path or page" );
2479 && ( instance.
m_Path.empty() ) )
2495 Expecting(
"path" );
2503 wxCHECK_RET( CurTok() == T_symbol_instances,
2504 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2505 wxCHECK( aScreen, );
2510 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2512 if( token != T_LEFT )
2513 Expecting( T_LEFT );
2530 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2532 if( token != T_LEFT )
2533 Expecting( T_LEFT );
2552 instance.
m_Value = FromUTF8();
2563 Expecting(
"path, unit, value or footprint" );
2572 Expecting(
"path" );
2581 wxCHECK( aSheet !=
nullptr, );
2585 wxCHECK( screen !=
nullptr, );
2587 if( aIsCopyableOnly )
2590 bool fileHasUuid =
false;
2604 if( !aIsCopyableOnly )
2609 if( CurTok() != T_kicad_sch )
2610 Expecting(
"kicad_sch" );
2626 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2628 if( aIsCopyableOnly && token == T_EOF )
2631 if( token != T_LEFT )
2632 Expecting( T_LEFT );
2662 case T_generator_version:
2688 if( aIsCopyableOnly )
2689 Unexpected( T_paper );
2699 if( aIsCopyableOnly )
2700 Unexpected( T_page );
2704 NeedSYMBOLorNUMBER();
2705 NeedSYMBOLorNUMBER();
2712 if( aIsCopyableOnly )
2713 Unexpected( T_title_block );
2727 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2729 if( token != T_LEFT )
2730 Expecting( T_LEFT );
2743 Expecting(
"symbol" );
2844 case T_netclass_flag:
2849 case T_global_label:
2850 case T_hierarchical_label:
2851 case T_directive_label:
2863 case T_sheet_instances:
2867 case T_symbol_instances:
2872 if( aIsCopyableOnly )
2873 Unexpected( T_bus_alias );
2878 case T_embedded_fonts:
2884 CurLineNumber(), CurOffset() );
2891 case T_embedded_files:
2897 CurLineNumber(), CurOffset() );
2900 embeddedFilesParser.SyncLineReaderWith( *
this );
2908 wxLogError( e.
What() );
2911 SyncLineReaderWith( embeddedFilesParser );
2917 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
2918 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
2919 "sheet, symbol, symbol_instances, text, title_block" );
2938 CurLineNumber(), CurOffset() );
2942 std::vector<std::string> fontNames;
2943 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
2953 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
2954 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
2959 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
2961 std::set<int> fieldIDsRead;
2974 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2976 if( token != T_LEFT )
2977 Expecting( T_LEFT );
2989 if( !IsSymbol( token ) )
2992 CurLineNumber(), CurOffset() );
2995 libName = FromUTF8();
2999 libName.Replace(
"{slash}",
"/" );
3009 if( !IsSymbol( token ) && token != T_NUMBER )
3010 Expecting(
"symbol|number" );
3013 wxString
name = FromUTF8();
3017 name.Replace(
"{slash}",
"/" );
3023 if(
static_cast<int>(
name.size() ) > bad_pos )
3025 wxString msg = wxString::Format(
3026 _(
"Symbol %s contains invalid character '%c'" ),
name,
3033 CurLineNumber(), CurOffset() );
3036 symbol->SetLibId( libId );
3042 symbol->SetPosition(
parseXY() );
3044 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
3047 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
3048 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
3049 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
3050 default: Expecting(
"0, 90, 180, or 270" );
3053 symbol->SetTransform( transform );
3062 else if( token == T_y )
3065 Expecting(
"x or y" );
3071 symbol->SetUnit(
parseInt(
"symbol unit" ) );
3078 symbol->SetBodyStyleUnconditional(
parseInt(
"symbol body style" ) );
3082 case T_exclude_from_sim:
3083 symbol->SetExcludedFromSim(
parseBool() );
3088 symbol->SetExcludedFromBOM( !
parseBool() );
3093 symbol->SetExcludedFromBoard( !
parseBool() );
3102 case T_fields_autoplaced:
3114 case T_default_instance:
3118 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3120 if( token != T_LEFT )
3121 Expecting( T_LEFT );
3140 symbol->SetValueFieldText( FromUTF8() );
3146 symbol->SetFootprintFieldText( FromUTF8() );
3151 Expecting(
"reference, unit, value or footprint" );
3160 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3162 if( token != T_LEFT )
3163 Expecting( T_LEFT );
3167 if( token != T_project )
3168 Expecting(
"project" );
3172 wxString projectName = FromUTF8();
3174 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3176 if( token != T_LEFT )
3177 Expecting( T_LEFT );
3181 if( token != T_path )
3182 Expecting(
"path" );
3191 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3193 if( token != T_LEFT )
3194 Expecting( T_LEFT );
3213 symbol->SetValueFieldText( FromUTF8() );
3219 symbol->SetFootprintFieldText( FromUTF8() );
3224 Expecting(
"reference, unit, value or footprint" );
3227 symbol->AddHierarchicalReference( instance );
3244 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3251 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3257 int nextAvailableId = field->
GetId() + 1;
3260 nextAvailableId += 1;
3262 field->
SetId( nextAvailableId );
3265 if( symbol->GetFieldById( field->
GetId() ) )
3266 *symbol->GetFieldById( field->
GetId() ) = *field;
3268 symbol->AddField( *field );
3271 symbol->UpdatePrefix();
3286 number = FromUTF8();
3288 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3290 if( token != T_LEFT )
3291 Expecting( T_LEFT );
3315 Expecting(
"alternate or uuid" );
3319 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3325 Expecting(
"lib_id, lib_name, at, mirror, uuid, on_board, in_bom, dnp, "
3326 "default_instance, property, pin, or instances" );
3330 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3331 symbol->SetSchSymbolLibraryName( libName );
3334 symbol->ClearFlags();
3336 return symbol.release();
3342 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3343 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3346 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3349 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3351 if( token != T_LEFT )
3352 Expecting( T_LEFT );
3359 bitmap->SetPosition(
parseXY() );
3385 data.reserve( 1 << 17 );
3387 while( token != T_RIGHT )
3389 if( !IsSymbol( token ) )
3390 Expecting(
"base64 image data" );
3396 wxMemoryBuffer buffer = wxBase64Decode( data );
3405 Expecting(
"at, scale, uuid or data" );
3418 return bitmap.release();
3424 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3425 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3431 std::vector<SCH_FIELD> fields;
3432 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3433 std::set<int> fieldIDsRead;
3438 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3440 if( token != T_LEFT )
3441 Expecting( T_LEFT );
3448 sheet->SetPosition(
parseXY() );
3457 sheet->SetSize( size );
3462 case T_exclude_from_sim:
3463 sheet->SetExcludedFromSim(
parseBool() );
3468 sheet->SetExcludedFromBOM( !
parseBool() );
3473 sheet->SetExcludedFromBoard( !
parseBool() );
3482 case T_fields_autoplaced:
3490 sheet->SetBorderWidth( stroke.
GetWidth() );
3491 sheet->SetBorderColor( stroke.
GetColor() );
3496 sheet->SetBackgroundColor( fill.
m_Color );
3513 if( fields.empty() )
3527 if( field->
GetId() < 0 )
3530 while( !fieldIDsRead.insert( field->
GetId() ).second )
3533 fields.emplace_back( *field );
3544 std::vector<SCH_SHEET_INSTANCE> instances;
3546 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3548 if( token != T_LEFT )
3549 Expecting( T_LEFT );
3553 if( token != T_project )
3554 Expecting(
"project" );
3558 wxString projectName = FromUTF8();
3560 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3562 if( token != T_LEFT )
3563 Expecting( T_LEFT );
3567 if( token != T_path )
3568 Expecting(
"path" );
3577 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3579 if( token != T_LEFT )
3580 Expecting( T_LEFT );
3600 static std::vector<wxString> whitespaces =
3606 for( wxString ch : whitespaces )
3615 Expecting(
"page" );
3619 instances.emplace_back( instance );
3623 sheet->setInstances( instances );
3628 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3632 sheet->SetFields( fields );
3634 return sheet.release();
3640 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3641 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3644 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3646 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3648 if( token != T_LEFT )
3649 Expecting( T_LEFT );
3656 junction->SetPosition(
parseXY() );
3674 junction->SetColor(
color );
3686 Expecting(
"at, diameter, color or uuid" );
3690 return junction.release();
3696 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3697 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3700 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3702 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3704 if( token != T_LEFT )
3705 Expecting( T_LEFT );
3712 no_connect->SetPosition(
parseXY() );
3723 Expecting(
"at or uuid" );
3727 return no_connect.release();
3733 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3734 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3738 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3740 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3742 if( token != T_LEFT )
3743 Expecting( T_LEFT );
3750 busEntry->SetPosition(
parseXY() );
3760 busEntry->SetSize( size );
3767 busEntry->SetStroke( stroke );
3777 Expecting(
"at, size, uuid or stroke" );
3781 return busEntry.release();
3801 std::unique_ptr<SCH_SHAPE> polyline = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_NOTES );
3803 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3805 if( token != T_LEFT )
3806 Expecting( T_LEFT );
3813 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3815 if( token != T_LEFT )
3816 Expecting( T_LEFT );
3823 polyline->AddPoint(
parseXY() );
3836 polyline->SetStroke( stroke );
3842 polyline->SetFillColor( fill.
m_Color );
3853 Expecting(
"pts, uuid, stroke, or fill" );
3857 return polyline.release();
3876 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
3879 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
3881 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3883 if( token != T_LEFT )
3884 Expecting( T_LEFT );
3897 line->SetStartPoint(
parseXY() );
3905 line->SetEndPoint(
parseXY() );
3912 line->SetStroke( stroke );
3922 Expecting(
"at, uuid or stroke" );
3926 return line.release();
3932 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
3933 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
3941 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
3943 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3945 if( token != T_LEFT )
3946 Expecting( T_LEFT );
3969 arc->SetStroke( stroke );
3975 arc->SetFillColor( fill.
m_Color );
3981 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
3986 Expecting(
"start, mid, end, stroke, fill or uuid" );
3990 arc->SetArcGeometry( startPoint, midPoint, endPoint );
3992 return arc.release();
3998 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
3999 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
4006 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
4008 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4010 if( token != T_LEFT )
4011 Expecting( T_LEFT );
4029 circle->SetStroke( stroke );
4035 circle->SetFillColor( fill.
m_Color );
4041 const_cast<KIID&
>( circle->m_Uuid ) =
KIID( FromUTF8() );
4046 Expecting(
"center, radius, stroke, fill or uuid" );
4050 circle->SetCenter(
center );
4053 return circle.release();
4059 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4060 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4065 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
4067 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4069 if( token != T_LEFT )
4070 Expecting( T_LEFT );
4077 rectangle->SetPosition(
parseXY() );
4082 rectangle->SetEnd(
parseXY() );
4088 rectangle->SetStroke( stroke );
4094 rectangle->SetFillColor( fill.
m_Color );
4100 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4105 Expecting(
"start, end, stroke, fill or uuid" );
4109 return rectangle.release();
4115 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4116 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4121 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4123 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4125 if( token != T_LEFT )
4126 Expecting( T_LEFT );
4140 ruleArea->SetPolyShape( sch_rule_poly );
4142 ruleArea->SetStroke( poly->GetStroke() );
4143 ruleArea->SetFillMode( poly->GetFillMode() );
4144 ruleArea->SetFillColor( poly->GetFillColor() );
4148 Expecting(
"polyline" );
4152 return ruleArea.release();
4158 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4159 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4164 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
4166 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4168 if( token != T_LEFT )
4169 Expecting( T_LEFT );
4179 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4181 if( token != T_LEFT )
4182 Expecting( T_LEFT );
4191 case 0: bezier->SetStart(
parseXY() );
break;
4192 case 1: bezier->SetBezierC1(
parseXY() );
break;
4193 case 2: bezier->SetBezierC2(
parseXY() );
break;
4194 case 3: bezier->SetEnd(
parseXY() );
break;
4195 default: Unexpected(
"control point" );
break;
4205 bezier->SetStroke( stroke );
4211 bezier->SetFillColor( fill.
m_Color );
4217 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4222 Expecting(
"pts, stroke, fill or uuid" );
4226 bezier->RebuildBezierToSegmentsPointsList( bezier->GetPenWidth() / 2 );
4228 return bezier.release();
4235 std::unique_ptr<SCH_TEXT>
text;
4239 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4240 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4241 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4242 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4243 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4244 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4246 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4254 text->SetText( FromUTF8() );
4256 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4258 if( token != T_LEFT )
4259 Expecting( T_LEFT );
4265 case T_exclude_from_sim:
4276 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4292 Unexpected( T_shape );
4300 case T_input: label->
SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
4301 case T_output: label->
SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
4302 case T_bidirectional: label->
SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
4303 case T_tri_state: label->
SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
4304 case T_passive: label->
SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
4305 case T_dot: label->
SetShape( LABEL_FLAG_SHAPE::F_DOT );
break;
4306 case T_round: label->
SetShape( LABEL_FLAG_SHAPE::F_ROUND );
break;
4307 case T_diamond: label->
SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
break;
4308 case T_rectangle: label->
SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
break;
4310 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4321 Unexpected( T_length );
4330 case T_fields_autoplaced:
4362 Unexpected( T_property );
4389 Expecting(
"at, shape, iref, uuid or effects" );
4395 if( label && label->
GetFields().empty() )
4398 return text.release();
4404 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4405 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4407 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4411 return textBox.release();
4417 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4418 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4420 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4424 return cell.release();
4440 bool foundEnd =
false;
4441 bool foundSize =
false;
4442 bool foundMargins =
false;
4446 aTextBox->
SetText( FromUTF8() );
4448 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4450 if( token != T_LEFT )
4451 Expecting( T_LEFT );
4457 case T_exclude_from_sim:
4488 cell->SetColSpan(
parseInt(
"column span" ) );
4489 cell->SetRowSpan(
parseInt(
"row span" ) );
4493 Expecting(
"at, size, stroke, fill, effects or uuid" );
4517 foundMargins =
true;
4533 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4535 Expecting(
"at, size, stroke, fill, effects or uuid" );
4543 else if( foundSize )
4544 aTextBox->
SetEnd( pos + size );
4546 Expecting(
"size" );
4561 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4562 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4566 STROKE_PARAMS borderStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4567 STROKE_PARAMS separatorsStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4568 std::unique_ptr<SCH_TABLE>
table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4570 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4572 if( token != T_LEFT )
4573 Expecting( T_LEFT );
4579 case T_column_count:
4584 case T_column_widths:
4588 while( ( token = NextTok() ) != T_RIGHT )
4598 while( ( token = NextTok() ) != T_RIGHT )
4605 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4607 if( token != T_LEFT )
4608 Expecting( T_LEFT );
4612 if( token != T_table_cell )
4613 Expecting(
"table_cell" );
4621 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4623 if( token != T_LEFT )
4624 Expecting( T_LEFT );
4642 table->SetBorderStroke( borderStroke );
4646 Expecting(
"external, header or stroke" );
4654 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4656 if( token != T_LEFT )
4657 Expecting( T_LEFT );
4675 table->SetSeparatorsStroke( separatorsStroke );
4679 Expecting(
"rows, cols, or stroke" );
4687 Expecting(
"columns, col_widths, row_heights, border, separators, header or cells" );
4691 return table.release();
4697 wxCHECK_RET( CurTok() == T_bus_alias,
4698 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4699 wxCHECK( aScreen, );
4702 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
4713 busAlias->SetName( alias );
4718 if( token != T_members )
4719 Expecting(
"members" );
4723 while( token != T_RIGHT )
4725 if( !IsSymbol( token ) )
4726 Expecting(
"quoted string" );
4728 member = FromUTF8();
4733 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)
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_FIELD_COUNT
The first 2 are mandatory, and must be instantiated in SCH_SHEET.
#define SHEET_MANDATORY_FIELDS
#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_FIELD_COUNT
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT, LIB_PART, and FOOTPRINT constru...
@ 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