7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-11 14:20:10 +00:00

Fix compatibility with EasyEDA/LCEDA Pro v2.2.26

Fixes https://gitlab.com/kicad/code/kicad/-/issues/18620
This commit is contained in:
Alex Shvartzkop 2024-08-30 04:38:22 +03:00
parent 660d26e572
commit 16d9fa7f25
5 changed files with 160 additions and 36 deletions

View File

@ -245,8 +245,17 @@ std::vector<nlohmann::json> EASYEDAPRO::ParseJsonLines( wxInputStream& aInput,
{
try
{
nlohmann::json js = nlohmann::json::parse( txt.ReadLine() );
lines.emplace_back( js );
wxString line = txt.ReadLine();
if( !line.IsEmpty() )
{
nlohmann::json js = nlohmann::json::parse( line );
lines.emplace_back( js );
}
else
{
lines.emplace_back( nlohmann::json() );
}
}
catch( nlohmann::json::exception& e )
{
@ -259,3 +268,42 @@ std::vector<nlohmann::json> EASYEDAPRO::ParseJsonLines( wxInputStream& aInput,
return lines;
}
std::vector<std::vector<nlohmann::json>>
EASYEDAPRO::ParseJsonLinesWithSeparation( wxInputStream& aInput, const wxString& aSource )
{
wxTextInputStream txt( aInput, wxS( " " ), wxConvUTF8 );
int currentLine = 1;
std::vector<std::vector<nlohmann::json>> lineBlocks;
lineBlocks.emplace_back();
while( aInput.CanRead() )
{
try
{
wxString line = txt.ReadLine();
if( !line.IsEmpty() )
{
nlohmann::json js = nlohmann::json::parse( line );
lineBlocks.back().emplace_back( js );
}
else
{
lineBlocks.emplace_back();
}
}
catch( nlohmann::json::exception& e )
{
wxLogWarning( wxString::Format( _( "Cannot parse JSON line %d in '%s': %s" ),
currentLine, aSource, e.what() ) );
}
currentLine++;
}
return lineBlocks;
}

View File

@ -57,6 +57,12 @@ void IterateZipFiles(
std::vector<nlohmann::json> ParseJsonLines( wxInputStream& aInput, const wxString& aSource );
/**
* Multiple document types (e.g. footprint and PCB) can be put into a single file, separated by empty line.
*/
std::vector<std::vector<nlohmann::json>> ParseJsonLinesWithSeparation( wxInputStream& aInput,
const wxString& aSource );
} // namespace EASYEDAPRO

View File

@ -36,7 +36,9 @@ void EASYEDAPRO::from_json( const nlohmann::json& j, EASYEDAPRO::SCH_ATTR& d )
d.id = j.at( 1 ).get<wxString>();
d.parentId = j.at( 2 ).get<wxString>();
d.key = j.at( 3 ).get<wxString>();
d.value = j.at( 4 ).get<wxString>();
if( j.at( 4 ).is_string() )
d.value = j.at( 4 ).get<wxString>();
if( j.at( 5 ).is_number() )
d.keyVisible = j.at( 5 ).get<int>();

View File

@ -122,6 +122,7 @@ BOARD* PCB_IO_EASYEDAPRO::LoadBoard( const wxString& aFileName, BOARD* aAppendTo
PCB_IO_EASYEDAPRO_PARSER parser( nullptr, nullptr );
wxFileName fname( aFileName );
wxString fpLibName = EASYEDAPRO::ShortenLibName( fname.GetName() );
if( fname.GetExt() == wxS( "epro" ) || fname.GetExt() == wxS( "zip" ) )
{
@ -167,7 +168,71 @@ BOARD* PCB_IO_EASYEDAPRO::LoadBoard( const wxString& aFileName, BOARD* aAppendTo
if( pcbUuid != pcbToLoad )
EASY_IT_CONTINUE;
std::vector<nlohmann::json> lines = EASYEDAPRO::ParseJsonLines( zip, name );
std::vector<nlohmann::json>* pcbLines = nullptr;
std::vector<std::vector<nlohmann::json>> lineBlocks =
EASYEDAPRO::ParseJsonLinesWithSeparation( zip, name );
if( lineBlocks.empty() )
EASY_IT_CONTINUE;
if( lineBlocks.size() > 1 )
{
for( std::vector<nlohmann::json>& block : lineBlocks )
{
wxString docType;
nlohmann::json headData;
for( const nlohmann::json& line : block )
{
if( line.size() < 2 )
continue;
if( !line.at( 0 ).is_string() )
continue;
wxString lineType = line.at( 0 ).get<wxString>();
if( lineType == wxS( "DOCTYPE" ) )
{
if( !line.at( 1 ).is_string() )
continue;
docType = line.at( 1 ).get<wxString>();
}
else if( lineType == wxS( "HEAD" ) )
{
if( !line.at( 1 ).is_object() )
continue;
headData = line.at( 1 );
}
}
if( docType == wxS( "FOOTPRINT" ) )
{
wxString fpUuid = headData.at( "uuid" );
wxString fpTitle = headData.at( "title" );
FOOTPRINT* footprint = parser.ParseFootprint( project, fpUuid, block );
if( !footprint )
EASY_IT_CONTINUE;
LIB_ID fpID = EASYEDAPRO::ToKiCadLibID( fpLibName, fpTitle );
footprint->SetFPID( fpID );
m_projectData->m_Footprints.emplace( fpUuid, footprint );
}
else if( docType == wxS( "PCB" ) )
{
pcbLines = &block;
}
}
}
if( pcbLines == nullptr )
pcbLines = &lineBlocks[0];
wxString boardKey = pcbUuid + wxS( "_0" );
wxScopedCharBuffer cb = boardKey.ToUTF8();
@ -177,7 +242,7 @@ BOARD* PCB_IO_EASYEDAPRO::LoadBoard( const wxString& aFileName, BOARD* aAppendTo
get_def( m_projectData->m_Poured, boardPouredKey );
parser.ParseBoard( m_board, project, m_projectData->m_Footprints,
m_projectData->m_Blobs, boardPoured, lines,
m_projectData->m_Blobs, boardPoured, *pcbLines,
EASYEDAPRO::ShortenLibName( fname.GetName() ) );
EASY_IT_BREAK;

View File

@ -794,50 +794,53 @@ FOOTPRINT* PCB_IO_EASYEDAPRO_PARSER::ParseFootprint( const nlohmann::json&
nlohmann::json polyDataList = line.at( 7 );
if( !polyDataList.at( 0 ).is_array() )
polyDataList = nlohmann::json::array( { polyDataList } );
std::vector<SHAPE_LINE_CHAIN> contours;
for( nlohmann::json& polyData : polyDataList )
if( !polyDataList.is_null() && !polyDataList.empty() )
{
SHAPE_LINE_CHAIN contour = ParseContour( polyData, false );
contour.SetClosed( true );
if( !polyDataList.at( 0 ).is_array() )
polyDataList = nlohmann::json::array( { polyDataList } );
contours.push_back( contour );
}
std::vector<SHAPE_LINE_CHAIN> contours;
for( nlohmann::json& polyData : polyDataList )
{
SHAPE_LINE_CHAIN contour = ParseContour( polyData, false );
contour.SetClosed( true );
SHAPE_POLY_SET polySet;
contours.push_back( contour );
}
for( SHAPE_LINE_CHAIN& contour : contours )
polySet.AddOutline( contour );
SHAPE_POLY_SET polySet;
polySet.RebuildHolesFromContours();
for( SHAPE_LINE_CHAIN& contour : contours )
polySet.AddOutline( contour );
std::unique_ptr<PCB_GROUP> group;
polySet.RebuildHolesFromContours();
if( polySet.OutlineCount() > 1 )
group = std::make_unique<PCB_GROUP>( footprint );
std::unique_ptr<PCB_GROUP> group;
BOX2I polyBBox = polySet.BBox();
if( polySet.OutlineCount() > 1 )
group = std::make_unique<PCB_GROUP>( footprint );
for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
{
std::unique_ptr<PCB_SHAPE> shape =
std::make_unique<PCB_SHAPE>( footprint, SHAPE_T::POLY );
BOX2I polyBBox = polySet.BBox();
shape->SetFilled( true );
shape->SetPolyShape( poly );
shape->SetLayer( klayer );
shape->SetWidth( 0 );
for( const SHAPE_POLY_SET::POLYGON& poly : polySet.CPolygons() )
{
std::unique_ptr<PCB_SHAPE> shape =
std::make_unique<PCB_SHAPE>( footprint, SHAPE_T::POLY );
shape->SetFilled( true );
shape->SetPolyShape( poly );
shape->SetLayer( klayer );
shape->SetWidth( 0 );
if( group )
group->AddItem( shape.get() );
footprint->Add( shape.release(), ADD_MODE::APPEND );
}
if( group )
group->AddItem( shape.get() );
footprint->Add( shape.release(), ADD_MODE::APPEND );
footprint->Add( group.release(), ADD_MODE::APPEND );
}
if( group )
footprint->Add( group.release(), ADD_MODE::APPEND );
}
else if( type == wxS( "ATTR" ) )
{