40#include <wx/mstream.h>
59static std::vector<std::vector<wxString>>
RegexMatchAll( wxRegEx& aRegex,
const wxString& aString )
61 std::vector<std::vector<wxString>> allMatches;
67 wxString str = aString;
69 while( aRegex.Matches( str ) )
71 std::vector<wxString> matches;
72 aRegex.GetMatch( &start, &len );
74 for(
size_t i = 0; i < aRegex.GetMatchCount(); i++ )
75 matches.emplace_back( aRegex.GetMatch( str, i ) );
77 allMatches.emplace_back( matches );
79 prevstart = start + len;
80 str = str.Mid( prevstart );
94static std::vector<std::pair<wxString, std::vector<double>>>
97 wxRegEx transformRegex(
"(rotate|translate|scale)\\(([\\w\\s,\\.\\-]*)\\)", wxRE_ICASE );
98 std::vector<std::vector<wxString>> allMatches =
RegexMatchAll( transformRegex, transformData );
100 std::vector<std::pair<wxString, std::vector<double>>> transformCmds;
102 for(
int cmdId = allMatches.size() - 1; cmdId >= 0; cmdId-- )
104 std::vector<wxString>& groups = allMatches[cmdId];
106 if( groups.size() != 3 )
109 const wxString& cmdName = groups[1].Strip( wxString::both ).Lower();
110 const wxString& cmdArgsStr = groups[2];
112 wxArrayString cmdParts = wxSplit( cmdArgsStr,
',',
'\0' );
113 std::vector<double> cmdArgs;
115 for(
const wxString& cmdPart : cmdParts )
118 wxASSERT( cmdPart.Strip( wxString::both ).ToCDouble( &arg ) );
120 cmdArgs.push_back( arg );
123 transformCmds.emplace_back( cmdName, cmdArgs );
126 return transformCmds;
134 wxString key = !aLibName.empty() ? ( aLibName +
':' + libReference ) : libReference;
137 libId.
Parse( key,
true );
145 if( aStyle == wxS(
"0" ) )
147 else if( aStyle == wxS(
"1" ) )
149 else if( aStyle == wxS(
"2" ) )
158 if( aType == wxS(
"0" ) )
160 else if( aType == wxS(
"1" ) )
162 else if( aType == wxS(
"2" ) )
164 else if( aType == wxS(
"3" ) )
166 else if( aType == wxS(
"4" ) )
358 aReporter->
Report(
_(
"Power Port with unknown style imported as 'Bar' type." ),
380 std::map<wxString, wxString> paramMap,
381 wxArrayString aShapes )
383 for( wxString shapeStr : aShapes )
385 wxArrayString arr = wxSplit( shapeStr,
'~',
'\0' );
387 wxString elType = arr[0];
388 if( elType == wxS(
"PL" ) || elType == wxS(
"PG" ) )
390 wxArrayString ptArr = wxSplit( arr[1],
' ',
'\0' );
391 wxString strokeColor = arr[2];
392 double lineWidth =
Convert( arr[3] );
394 wxString fillColor = arr[5].Lower();
399 for(
size_t i = 1; i < ptArr.size(); i += 2 )
405 auto line = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_DEVICE );
407 if( elType == wxS(
"PG" ) )
414 line->AddPoint( chain.
CPoint( i ) );
417 line->AddPoint( chain.
CPoint( 0 ) );
422 if( fillColor != wxS(
"none" ) )
424 line->SetFilled(
true );
426 if( fillColor == strokeColor )
427 line->SetFillMode( FILL_T::FILLED_SHAPE );
429 line->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
434 else if( elType == wxS(
"PT" ) )
436 wxString pointsData = arr[1];
437 wxString strokeColor = arr[2];
438 double lineWidth =
Convert( arr[3] );
440 wxString fillColor = arr[5].Lower();
443 std::vector<SHAPE_LINE_CHAIN> lineChains =
448 auto shape = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_DEVICE );
450 outline.Mirror(
false,
true );
452 if( outline.IsClosed() )
453 outline.Append( outline.CPoint( 0 ),
true );
455 for(
const VECTOR2I& pt : outline.CPoints() )
456 shape->AddPoint( pt );
461 if( fillColor != wxS(
"none" ) )
463 shape->SetFilled(
true );
465 if( fillColor == strokeColor )
466 shape->SetFillMode( FILL_T::FILLED_SHAPE );
468 shape->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
474 else if( elType == wxS(
"Pimage" ) )
479 wxString imageUrl = arr[10];
481 if( imageUrl.BeforeFirst(
':' ) == wxS(
"data" ) )
483 wxArrayString paramsArr =
484 wxSplit( imageUrl.AfterFirst(
':' ).BeforeFirst(
',' ),
';',
'\0' );
486 wxString data = imageUrl.AfterFirst(
',' );
488 if( paramsArr.size() > 0 )
490 wxString mimeType = paramsArr[0];
491 wxMemoryBuffer buf = wxBase64Decode( data );
493 if( mimeType == wxS(
"image/svg+xml" ) )
509 libsymImporter.
SetScale( pixelScale );
518 for( std::unique_ptr<EDA_ITEM>& item : libsymImporter.
GetItems() )
523 wxMemoryInputStream memis( buf.GetData(), buf.GetDataLen() );
525 wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
526 & ~wxImage::Load_Verbose );
528 if( img.LoadFile( memis, mimeType ) )
530 int dimMul = img.GetWidth() * img.GetHeight();
531 double maxPixels = 30000;
533 if( dimMul > maxPixels )
535 double scale = sqrt( maxPixels / dimMul );
536 img.Rescale( img.GetWidth() *
scale, img.GetHeight() *
scale );
549 else if( elType == wxS(
"A" ) )
551 wxString data = arr[1];
552 wxString strokeColor = arr[3];
553 double lineWidth =
Convert( arr[4] );
555 wxString fillColor = arr[6].Lower();
564 auto readNumber = [&]( wxString& aOut )
566 wxUniChar ch = data[pos];
568 while( ch ==
' ' || ch ==
',' )
571 while( isdigit( ch ) || ch ==
'.' || ch ==
'-' )
576 if( pos == data.size() )
585 wxUniChar sym = data[pos++];
595 else if( sym ==
'A' )
597 wxString radX, radY,
unknown, farFlag, cwFlag, endX, endY;
601 readNumber( farFlag );
602 readNumber( cwFlag );
606 isFar = farFlag == wxS(
"1" );
607 cw = cwFlag == wxS(
"1" );
611 }
while( pos < data.size() );
615 double avgRad = ( rad.
x + rad.
y ) / 2;
616 double d =
delta.EuclideanNorm();
617 double h = sqrt( std::max( 0.0, avgRad * avgRad - d * d / 4 ) );
624 start +
delta / 2 +
delta.Perpendicular().Resize( ( isFar ^ cw ) ? h : -h );
627 std::swap( start, end );
629 auto shape = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC,
LAYER_DEVICE );
633 shape->SetCenter(
RelPosSym( arcCenter ) );
638 if( fillColor != wxS(
"none" ) )
640 shape->SetFilled(
true );
642 if( fillColor == strokeColor )
643 shape->SetFillMode( FILL_T::FILLED_SHAPE );
645 shape->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
650 else if( elType == wxS(
"R" ) )
655 cr.
x = !arr[3].empty() ?
Convert( arr[3] ) : 0,
656 cr.
y = !arr[4].empty() ?
Convert( arr[4] ) : 0;
659 wxString strokeColor = arr[7];
660 double lineWidth =
Convert( arr[8] );
662 wxString fillColor = arr[10].Lower();
667 auto rect = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE,
LAYER_DEVICE );
670 rect->SetEnd(
RelPosSym( start + size ) );
675 if( fillColor != wxS(
"none" ) )
677 rect->SetFilled(
true );
679 if( fillColor == strokeColor )
680 rect->SetFillMode( FILL_T::FILLED_SHAPE );
682 rect->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
689 else if( elType == wxS(
"E" ) )
691 auto circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE,
LAYER_DEVICE );
695 wxString strokeColor = arr[5];
696 double lineWidth =
Convert( arr[6] );
698 wxString fillColor = arr[8].Lower();
701 circle->SetCenter(
RelPosSym( center ) );
704 circle->SetUnit( 0 );
707 if( fillColor != wxS(
"none" ) )
709 circle->SetFilled(
true );
711 if( fillColor == strokeColor )
712 circle->SetFillMode( FILL_T::FILLED_SHAPE );
714 circle->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
719 else if( elType == wxS(
"P" ) )
721 wxString sepShapeStr = shapeStr;
722 sepShapeStr.Replace( wxS(
"^^" ), wxS(
"\n" ) );
724 wxArrayString segments = wxSplit( sepShapeStr,
'\n',
'\0' );
725 wxArrayString mainParts = wxSplit( segments[0],
'~',
'\0' );
726 wxArrayString pinDotParts = wxSplit( segments[1],
'~',
'\0' );
727 wxArrayString pinPathColorParts = wxSplit( segments[2],
'~',
'\0' );
728 wxArrayString pinNameParts = wxSplit( segments[3],
'~',
'\0' );
729 wxArrayString pinNumParts = wxSplit( segments[4],
'~',
'\0' );
733 wxString pinNumber = mainParts[3];
739 bool nameVisible = pinNameParts[0] != wxS(
"0" );
740 wxString pinName = pinNameParts[4];
742 bool numVisible = pinNumParts[0] != wxS(
"0" );
743 wxString ptSize = pinNumParts[4];
746 bool vertical =
false;
750 wxString lineData = pinPathColorParts[0];
751 wxRegEx regex( wxS(
"^M\\s*([-\\d.]+)[,\\s]([-\\d.]+)\\s*([h|v])\\s*([-\\d.]+)\\s*$" ) );
753 if( regex.Matches( lineData ) )
755 startPoint.
x =
Convert( regex.GetMatch( lineData, 1 ) );
756 startPoint.
y =
Convert( regex.GetMatch( lineData, 2 ) );
758 vertical = regex.GetMatch( lineData, 3 ).Contains( wxS(
"v" ) );
759 pinLen =
Convert( regex.GetMatch( lineData, 4 ) );
766 if( startPoint.
x == pinPos.
x && pinLen < 0 )
768 else if( startPoint.
x == pinPos.
x && pinLen > 0 )
770 else if( startPoint.
x != pinPos.
x && pinLen < 0 )
772 else if( startPoint.
x != pinPos.
x && pinLen > 0 )
777 if( startPoint.
y == pinPos.
y && pinLen < 0 )
779 else if( startPoint.
y == pinPos.
y && pinLen > 0 )
781 else if( startPoint.
y != pinPos.
y && pinLen < 0 )
783 else if( startPoint.
y != pinPos.
y && pinLen > 0 )
789 if( pinRotation == 0 )
790 orient = PIN_ORIENTATION::PIN_RIGHT;
791 else if( pinRotation == 90 )
792 orient = PIN_ORIENTATION::PIN_UP;
793 else if( pinRotation == 180 )
794 orient = PIN_ORIENTATION::PIN_LEFT;
795 else if( pinRotation == 270 )
796 orient = PIN_ORIENTATION::PIN_DOWN;
801 if( segments.size() > 5 )
803 wxArrayString dotParts = wxSplit( segments[5],
'~',
'\0' );
804 wxArrayString clockParts = wxSplit( segments[6],
'~',
'\0' );
806 if( dotParts.size() == 3 && clockParts.size() == 2 )
808 if( dotParts[0] == wxS(
"1" ) )
812 auto circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE,
LAYER_DEVICE );
814 circle->SetCenter(
RelPosSym( dotPos ) );
816 pinPos + ( dotPos - pinPos ).Resize(
std::abs( pinLen ) ) ) );
818 circle->SetUnit( 0 );
823 if( clockParts[0] == wxS(
"1" ) )
825 std::vector<SHAPE_LINE_CHAIN> lineChains =
830 auto shape = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_DEVICE );
832 outline.Mirror(
false,
true );
834 if( outline.IsClosed() )
835 outline.Append( outline.CPoint( 0 ),
true );
837 for(
const VECTOR2I& pt : outline.CPoints() )
838 shape->AddPoint( pt );
848 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>( aSymbol );
850 pin->SetName( pinName );
851 pin->SetNumber( pinNumber );
852 pin->SetOrientation( orient );
853 pin->SetType( elecType );
854 pin->SetLength( kPinLen );
856 pin->SetUnit( pinUnit );
858 if(
pin->GetNumberTextSize() *
int( pinNumber.size() ) > kPinLen )
859 pin->SetNumberTextSize( kPinLen / pinNumber.size() );
869 else if( elType == wxS(
"T" ) )
871 wxString textType = arr[1];
874 wxString
color = arr[5];
875 wxString fontname = arr[6];
876 wxString fontSize = arr[7];
877 wxString baselineAlign = arr[10];
878 wxString textStr = arr[12];
879 bool visible = arr[13] != wxS(
"0" );
881 textStr.Replace( wxS(
"\\n" ), wxS(
"\n" ) );
884 wxString halignStr = arr[14];
889 if( textType == wxS(
"P" ) )
895 else if( textType == wxS(
"N" ) )
910 if( halignStr == wxS(
"middle" ) )
912 else if( halignStr == wxS(
"end" ) )
922 if( !fontSize.IsEmpty() )
924 if( fontSize.EndsWith( wxS(
"pt" ) ) )
925 ptSize =
Convert( fontSize.BeforeFirst(
'p' ) );
926 else if( fontSize.IsNumber() )
932 if( textStr.Contains( wxS(
"\n" ) ) )
949 std::map<wxString, wxString> aParams,
950 wxArrayString aShapes )
952 std::unique_ptr<LIB_SYMBOL> ksymbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
956 wxString symbolName = wxS(
"Unknown" );
958 if( aParams.find( wxS(
"name" ) ) != aParams.end() )
959 symbolName = aParams.at( wxS(
"name" ) );
960 else if( aParams.find( wxS(
"spiceSymbolName" ) ) != aParams.end() )
961 symbolName = aParams.at( wxS(
"spiceSymbolName" ) );
963 wxString symbolPrefix;
965 if( aParams.find( wxS(
"pre" ) ) != aParams.end() )
966 symbolPrefix = aParams.at( wxS(
"pre" ) );
967 else if( aParams.find( wxS(
"spicePre" ) ) != aParams.end() )
968 symbolPrefix = aParams.at( wxS(
"spicePre" ) );
970 if( !symbolPrefix.EndsWith( wxS(
"?" ) ) )
971 symbolPrefix += wxS(
"?" );
975 ksymbol->SetLibId( libId );
976 ksymbol->SetName( symbolName );
978 ksymbol->GetReferenceField().SetText( symbolPrefix );
979 ksymbol->GetValueField().SetText( symbolName );
983 return ksymbol.release();
987 const wxString& aNetname )
989 std::unique_ptr<LIB_SYMBOL> ksymbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
996 ksymbol->SetLibId( libId );
997 ksymbol->SetName( aNetname );
998 ksymbol->GetReferenceField().SetText( wxS(
"#PWR" ) );
999 ksymbol->GetReferenceField().SetVisible(
false );
1000 ksymbol->GetValueField().SetText( aNetname );
1001 ksymbol->GetValueField().SetVisible(
true );
1002 ksymbol->SetDescription( wxString::Format(
_(
"Power symbol creates a global "
1003 "label with name '%s'" ),
1005 ksymbol->SetKeyWords( wxS(
"power-flag" ) );
1006 ksymbol->SetShowPinNames(
false );
1007 ksymbol->SetShowPinNumbers(
false );
1009 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>( ksymbol.get() );
1011 pin->SetName( aNetname );
1012 pin->SetNumber( wxS(
"1" ) );
1013 pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN );
1014 pin->SetType( ELECTRICAL_PINTYPE::PT_POWER_IN );
1015 pin->SetLength( 0 );
1017 ksymbol->AddDrawItem(
pin.release() );
1023 if( aFlagTypename == wxS(
"part_netLabel_gnD" ) )
1027 else if( aFlagTypename == wxS(
"part_netLabel_GNd" ) )
1031 else if( aFlagTypename == wxS(
"part_netLabel_gNd" ) )
1035 else if( aFlagTypename == wxS(
"part_netLabel_GnD" ) )
1039 else if( aFlagTypename == wxS(
"part_netLabel_VCC" ) )
1044 else if( aFlagTypename == wxS(
"part_netLabel_+5V" ) )
1049 else if( aFlagTypename == wxS(
"part_netLabel_VEE" ) )
1053 else if( aFlagTypename == wxS(
"part_netLabel_-5V" ) )
1057 else if( aFlagTypename == wxS(
"part_netLabel_Bar" ) )
1064 ksymbol->GetValueField().SetPosition( valueFieldPos );
1066 return std::make_pair( ksymbol.release(), flip );
1070 const wxString& aFileName, wxArrayString aShapes )
1072 std::map<wxString, std::unique_ptr<LIB_SYMBOL>> loadedSymbols;
1073 std::map<wxString, int> namesCounter;
1074 std::vector<std::unique_ptr<SCH_ITEM>> createdItems;
1076 for( wxString shap : aShapes )
1078 shap.Replace( wxS(
"#@$" ), wxS(
"\n" ) );
1079 wxArrayString parts = wxSplit( shap,
'\n',
'\0' );
1081 if( parts.size() < 1 )
1084 wxArrayString arr = wxSplit( parts[0],
'~',
'\0' );
1086 if( arr.size() < 1 )
1089 wxString rootType = arr[0];
1091 if( rootType == wxS(
"LIB" ) )
1093 if( arr.size() < 4 )
1098 wxString symbolName = wxString::Format( wxS(
"Unknown_%s_%s" ), arr[1], arr[2] );
1100 wxArrayString paramParts = wxSplit( arr[3],
'`',
'\0' );
1102 std::map<wxString, wxString> paramMap;
1104 for(
size_t i = 1; i < paramParts.size(); i += 2 )
1106 wxString key = paramParts[i - 1];
1107 wxString value = paramParts[i];
1109 if( key == wxS(
"spiceSymbolName" ) && !value.IsEmpty() )
1112 paramMap[key] = value;
1115 int& serial = namesCounter[symbolName];
1118 symbolName << wxS(
"_" ) << serial;
1122 paramMap[wxS(
"spiceSymbolName" )] = symbolName;
1124 parts.RemoveAt( 0 );
1129 loadedSymbols.emplace( symbolName, sym );
1136 std::unique_ptr<SCH_SYMBOL> schSym =
1137 std::make_unique<SCH_SYMBOL>( *sym, libId, &aSchematic->
CurrentSheet(), 0 );
1139 schSym->SetPosition(
RelPos( origin ) );
1140 schSym->SetRef( &aSchematic->
CurrentSheet(), referenceStr );
1142 createdItems.push_back( std::move( schSym ) );
1144 else if( rootType == wxS(
"F" ) )
1146 wxString sepShapeStr = parts[0];
1147 sepShapeStr.Replace( wxS(
"^^" ), wxS(
"\n" ) );
1149 wxArrayString segments = wxSplit( sepShapeStr,
'\n',
'\0' );
1150 wxArrayString mainParts = wxSplit( segments[0],
'~',
'\0' );
1151 wxArrayString uselessParts = wxSplit( segments[1],
'~',
'\0' );
1152 wxArrayString valueParts = wxSplit( segments[2],
'~',
'\0' );
1154 wxString flagTypename = arr[1];
1156 double angle =
Convert( arr[4] );
1158 wxString netnameValue = valueParts[0];
1160 double textAngle =
Convert( valueParts[4] );
1161 wxString halignStr = valueParts[5];
1162 wxString valueFontname = valueParts[7];
1163 wxString valueFontsize = valueParts[8];
1165 if( flagTypename == wxS(
"part_netLabel_netPort" ) )
1167 std::unique_ptr<SCH_GLOBALLABEL> label =
1168 std::make_unique<SCH_GLOBALLABEL>(
RelPos( pos ), netnameValue );
1172 for(
double i = angle; i > 0; i -= 90 )
1176 if( segments.size() > 3 )
1178 wxArrayString shapeParts = wxSplit( segments[3],
'~',
'\0' );
1179 if( shapeParts[0] == wxS(
"PL" ) )
1181 wxArrayString ptArr = wxSplit( shapeParts[1],
' ',
'\0' );
1185 for(
size_t i = 1; i < ptArr.size(); i += 2 )
1197 if( shapeCenter.
x >= 0 )
1204 if( shapeCenter.
y >= 0 )
1212 label->SetSpinStyle( spin );
1213 label->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
1215 createdItems.push_back( std::move( label ) );
1221 bool flip = pair.second;
1225 std::unique_ptr<SCH_SYMBOL> schSym = std::make_unique<SCH_SYMBOL>(
1234 else if( angle == 90 )
1248 schSym->SetPosition(
RelPos( pos ) );
1260 if( halignStr == wxS(
"middle" ) )
1262 else if( halignStr == wxS(
"end" ) )
1267 if( flip && ( angle == 90 || angle == 270 ) )
1279 if( flagTypename == wxS(
"part_netLabel_Bar" ) )
1283 if( angle == 0 && flagTypename == wxS(
"part_netLabel_Bar" ) )
1290 if( valueFontsize.EndsWith( wxS(
"pt" ) ) )
1291 ptSize =
Convert( valueFontsize.BeforeFirst(
'p' ) );
1295 if( netnameValue.Contains( wxS(
"\n" ) ) )
1304 createdItems.push_back( std::move( schSym ) );
1307 else if( rootType == wxS(
"W" ) )
1309 wxArrayString ptArr = wxSplit( arr[1],
' ',
'\0' );
1310 wxString strokeColor = arr[2];
1313 wxString fillColor = arr[5].Lower();
1318 for(
size_t i = 1; i < ptArr.size(); i += 2 )
1321 for(
int segId = 0; segId < chain.
SegmentCount(); segId++ )
1325 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>( seg.
A,
LAYER_WIRE );
1326 line->SetEndPoint( seg.
B );
1328 createdItems.push_back( std::move( line ) );
1331 else if( rootType == wxS(
"N" ) )
1334 double angle =
Convert( arr[3] );
1335 wxString netname = arr[5];
1336 wxString halignStr = arr[7];
1340 wxString fontname = arr[10];
1341 wxString fontSize = arr[11];
1343 std::unique_ptr<SCH_LABEL> label =
1344 std::make_unique<SCH_LABEL>(
RelPos( pos ), netname );
1346 if( halignStr == wxS(
"middle" ) )
1348 else if( halignStr == wxS(
"end" ) )
1354 label->Rotate90(
false );
1356 createdItems.push_back( std::move( label ) );
1358 else if( rootType == wxS(
"O" ) )
1362 std::unique_ptr<SCH_NO_CONNECT> noConn =
1363 std::make_unique<SCH_NO_CONNECT>(
RelPos( pos ) );
1365 createdItems.push_back( std::move( noConn ) );
1367 else if( rootType == wxS(
"J" ) )
1372 std::unique_ptr<SCH_JUNCTION> junction =
1373 std::make_unique<SCH_JUNCTION>(
RelPos( pos ) );
1375 createdItems.push_back( std::move( junction ) );
1377 else if( rootType == wxS(
"T" ) )
1380 int angle =
Convert( arr[4] );
1381 wxString
color = arr[5];
1382 wxString fontname = arr[6];
1383 wxString fontSize = arr[7];
1384 wxString baselineAlign = arr[10];
1385 wxString textStr = arr[12];
1387 textStr.Replace( wxS(
"\\n" ), wxS(
"\n" ) );
1390 wxString halignStr = arr[14];
1392 std::unique_ptr<SCH_TEXT> textItem =
1393 std::make_unique<SCH_TEXT>(
RelPos( pos ), textStr );
1395 textItem->SetTextAngleDegrees( ( 360 - angle ) % 360 );
1398 if( halignStr == wxS(
"middle" ) )
1400 else if( halignStr == wxS(
"end" ) )
1409 if( fontSize.EndsWith( wxS(
"pt" ) ) )
1410 ptSize =
Convert( fontSize.BeforeFirst(
'p' ) );
1414 if( textStr.Contains( wxS(
"\n" ) ) )
1419 textItem->SetTextSize(
VECTOR2I( ktextSize, ktextSize ) );
1423 createdItems.push_back( std::move( textItem ) );
1425 else if( rootType == wxS(
"R" ) )
1430 cr.
x = !arr[3].empty() ?
Convert( arr[3] ) : 0,
1431 cr.
y = !arr[4].empty() ?
Convert( arr[4] ) : 0;
1434 wxString strokeColor = arr[7];
1435 double lineWidth =
Convert( arr[8] );
1437 wxString fillColor = arr[10].Lower();
1442 std::unique_ptr<SCH_SHAPE> rect = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
1444 rect->SetStart(
RelPos( start ) );
1445 rect->SetEnd(
RelPos( start + size ) );
1449 if( fillColor != wxS(
"none" ) )
1451 rect->SetFilled(
true );
1453 if( fillColor == strokeColor )
1454 rect->SetFillMode( FILL_T::FILLED_SHAPE );
1456 rect->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
1459 createdItems.push_back( std::move( rect ) );
1465 else if( rootType == wxS(
"I" ) )
1470 wxString imageUrl = arr[6];
1471 wxString transformData = arr[9];
1476 std::vector<std::pair<wxString, std::vector<double>>> transformCmds =
1479 auto applyTransform = [&](
SCH_ITEM* aSchItem )
1481 for(
const auto& cmd : transformCmds )
1483 if( cmd.first == wxS(
"rotate" ) )
1485 if( cmd.second.size() != 3 )
1488 double cmdAngle = 360 - cmd.second[0];
1489 VECTOR2D cmdAround( cmd.second[1], cmd.second[2] );
1491 for(
double i = cmdAngle; i > 0; i -= 90 )
1497 aSchItem->Rotate(
RelPos( cmdAround ),
false );
1501 aSchItem->Rotate(
RelPos( cmdAround ),
false );
1506 aSchItem->Rotate(
RelPos( cmdAround ),
false );
1510 else if( cmd.first == wxS(
"translate" ) )
1512 if( cmd.second.size() != 2 )
1515 VECTOR2D cmdOffset( cmd.second[0], cmd.second[1] );
1516 aSchItem->Move(
ScalePos( cmdOffset ) );
1518 else if( cmd.first == wxS(
"scale" ) )
1520 if( cmd.second.size() != 2 )
1523 double cmdScaleX = cmd.second[0];
1524 double cmdScaleY = cmd.second[1];
1530 if( cmdScaleX < 0 && cmdScaleY > 0 )
1532 aSchItem->MirrorHorizontally( 0 );
1534 else if( cmdScaleX > 0 && cmdScaleY < 0 )
1536 aSchItem->MirrorVertically( 0 );
1538 else if( cmdScaleX < 0 && cmdScaleY < 0 )
1540 aSchItem->MirrorHorizontally( 0 );
1541 aSchItem->MirrorVertically( 0 );
1550 if( imageUrl.BeforeFirst(
':' ) == wxS(
"data" ) )
1552 wxArrayString paramsArr =
1553 wxSplit( imageUrl.AfterFirst(
':' ).BeforeFirst(
',' ),
';',
'\0' );
1555 wxString data = imageUrl.AfterFirst(
',' );
1557 if( paramsArr.size() > 0 )
1559 wxString mimeType = paramsArr[0];
1560 wxMemoryBuffer buf = wxBase64Decode( data );
1562 if( mimeType == wxS(
"image/svg+xml" ) )
1578 schImporter.
SetScale( pixelScale );
1585 svgImportPlugin.
Import();
1587 for( std::unique_ptr<EDA_ITEM>& item : schImporter.
GetItems() )
1591 applyTransform( schItem );
1593 createdItems.emplace_back( schItem );
1598 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
1600 wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
1601 & ~wxImage::Load_Verbose );
1603 if( bitmap->ReadImageFile( buf ) )
1605 VECTOR2D kcenter = kstart + ksize / 2;
1607 double scaleFactor =
ScaleSize( size.
x ) / bitmap->GetSize().x;
1608 bitmap->SetImageScale( scaleFactor );
1609 bitmap->SetPosition( kcenter );
1611 applyTransform( bitmap.get() );
1613 createdItems.push_back( std::move( bitmap ) );
1623 for( std::unique_ptr<SCH_ITEM>& ptr : createdItems )
1633 offset.
x =
KiROUND( offset.
x / alignGrid ) * alignGrid;
1634 offset.
y =
KiROUND( offset.
y / alignGrid ) * alignGrid;
1641 for( std::unique_ptr<SCH_ITEM>& ptr : createdItems )
1643 ptr->Move( offset );
1644 screen->
Append( ptr.release() );
constexpr EDA_IU_SCALE schIUScale
size_type GetHeight() const
coord_type GetTop() const
size_type GetWidth() const
coord_type GetLeft() const
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
std::vector< SHAPE_LINE_CHAIN > ParseLineChains(const wxString &aData, int aArcMinSegLen, bool aForceClosed)
static double Convert(const wxString &aValue)
void TransformTextToBaseline(EDA_TEXT *textItem, const wxString &baselineAlign, bool invertY)
double RelPosX(double aValue)
double RelPosY(double aValue)
VECTOR2< T > RelPos(const VECTOR2< T > &aVec)
VECTOR2< T > ScalePos(const VECTOR2< T > &aValue)
void SetEnd(const VECTOR2I &aEnd)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
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)
GR_TEXT_H_ALIGN_T GetHorizJustify() const
virtual void SetVisible(bool aVisible)
void SetTextAngleDegrees(double aOrientation)
GR_TEXT_V_ALIGN_T GetVertJustify() const
virtual void SetText(const wxString &aText)
void SetFont(KIFONT::FONT *aFont)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
void SetImportOffsetMM(const VECTOR2D &aOffset)
Set the offset in millimeters to add to coordinates when importing graphic items.
void SetScale(const VECTOR2D &aScale)
Set the scale factor affecting the imported shapes.
std::list< std::unique_ptr< EDA_ITEM > > & GetItems()
Return the list of objects representing the imported shapes.
virtual void SetImporter(GRAPHICS_IMPORTER *aImporter)
Set the receiver of the imported shapes.
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
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.
SCH_FIELD & GetValueField() const
Return reference to the value field.
SCH_FIELD & GetReferenceField() const
Return reference to the reference designator field.
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetHeightMils(double aHeightInMils)
void SetWidthMils(double aWidthInMils)
A progress reporter interface for use in multi-threaded environments.
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
Holds all the data relating to one schematic.
SCH_SHEET_PATH & CurrentSheet() const override
void ParseSymbolShapes(LIB_SYMBOL *aContainer, std::map< wxString, wxString > paramMap, wxArrayString aShapes)
std::pair< LIB_SYMBOL *, bool > MakePowerSymbol(const wxString &aFlagTypename, const wxString &aNetname)
double ScaleSize(double aValue) override
void ParseSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const wxString &aFileName, wxArrayString aShapes)
VECTOR2< T > RelPosSym(const VECTOR2< T > &aVec)
LIB_SYMBOL * ParseSymbol(const VECTOR2D &aOrigin, std::map< wxString, wxString > aParams, wxArrayString aShapes)
SCH_EASYEDA_PARSER(SCHEMATIC *aSchematic, PROGRESS_REPORTER *aProgressReporter)
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
void SetPosition(const VECTOR2I &aPosition) override
Base class for any item which can be embedded within the SCHEMATIC container class,...
const PAGE_INFO & GetPageSettings() const
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void SetPageSettings(const PAGE_INFO &aPageSettings)
void SetPosition(const VECTOR2I &aPos) override
void SetStroke(const STROKE_PARAMS &aStroke) override
void AddPoint(const VECTOR2I &aPosition)
VECTOR2I GetPosition() const override
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
SCH_SCREEN * GetScreen() const
BOX2I GetBodyBoundingBox() const
Return a bounding box for the symbol body but not the pins or fields.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void Move(const VECTOR2I &aVector) override
bool IsClosed() const override
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
virtual VECTOR2I Centre() const
Compute a center-of-mass of the shape.
Simple container to manage line stroke parameters.
bool Import() override
Actually imports the file.
virtual double GetImageWidth() const override
Return image width from original imported file.
bool LoadFromMemory(const wxMemoryBuffer &aMemBuffer) override
Set memory buffer with content for import.
virtual double GetImageHeight() const override
Return image height from original imported file.
#define ENDPOINT
ends. (Used to support dragging.)
#define STARTPOINT
When a line is selected, these flags indicate which.
void ConvertImageToLibShapes(LIB_SYMBOL *aSymbol, int unit, wxImage img, VECTOR2D pixelScale, VECTOR2D offset)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
@ PT_INPUT
usual pin input: must be connected
@ PT_BIDI
input or output (like port for a microprocessor)
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin
PIN_ORIENTATION
The symbol library pin object orientations.
static std::vector< std::vector< wxString > > RegexMatchAll(wxRegEx &aRegex, const wxString &aString)
static ELECTRICAL_PINTYPE ConvertElecType(const wxString &aType)
VECTOR2I HelperGeneratePowerPortGraphics(LIB_SYMBOL *aKsymbol, EASYEDA::POWER_FLAG_STYLE aStyle, REPORTER *aReporter)
static LIB_ID EasyEdaToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
static std::vector< std::pair< wxString, std::vector< double > > > ParseImageTransform(const wxString &transformData)
EasyEDA image transformations are in the form of:
static LINE_STYLE ConvertStrokeStyle(const wxString &aStyle)
VECTOR2I HelperGeneratePowerPortGraphics(LIB_SYMBOL *aKsymbol, ASCH_POWER_PORT_STYLE aStyle, REPORTER *aReporter)
@ SYM_ROTATE_COUNTERCLOCKWISE
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
wxString UnescapeHTML(const wxString &aString)
Return a new wxString unescaped from HTML format.
LINE_STYLE
Dashed line types.
constexpr double IUTomm(int iu) const
constexpr int IUToMils(int iu) const
constexpr int MilsToIU(int mils) const
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
VECTOR2< double > VECTOR2D