265                                  bool aClosed, 
bool aInFill )
 const 
  267    std::vector<std::unique_ptr<PCB_SHAPE>> results;
 
  270    for( 
int i = 0; i < polyData.size(); i++ )
 
  272        nlohmann::json val = polyData.at( i );
 
  274        if( val.is_string() )
 
  277            if( str == wxS( 
"CIRCLE" ) )
 
  280                center.x = ( polyData.at( ++i ) );
 
  281                center.y = ( polyData.at( ++i ) );
 
  282                double r = ( polyData.at( ++i ) );
 
  284                std::unique_ptr<PCB_SHAPE> shape =
 
  289                shape->SetFilled( aClosed );
 
  291                results.emplace_back( std::move( shape ) );
 
  293            else if( str == wxS( 
"R" ) )
 
  296                start.
x = ( polyData.at( ++i ) );
 
  297                start.
y = ( polyData.at( ++i ) );
 
  298                size.
x = ( polyData.at( ++i ) );
 
  299                size.
y = -( polyData.at( ++i ).get<double>() );
 
  300                double angle = polyData.at( ++i );
 
  301                double cr = ( i + 1 ) < polyData.size() ? polyData.at( ++i ).get<
double>() : 0;
 
  305                    std::unique_ptr<PCB_SHAPE> shape =
 
  308                    shape->SetStart( 
ScalePos( start ) );
 
  309                    shape->SetEnd( 
ScalePos( start + size ) );
 
  310                    shape->SetFilled( aClosed );
 
  313                    results.emplace_back( std::move( shape ) );
 
  321                        std::unique_ptr<PCB_SHAPE> shape =
 
  324                        shape->SetStart( 
ScalePos( aStart ) );
 
  326                        shape->SetFilled( aClosed );
 
  329                        results.emplace_back( std::move( shape ) );
 
  334                        std::unique_ptr<PCB_SHAPE> shape =
 
  335                                std::make_unique<PCB_SHAPE>( aContainer, 
SHAPE_T::ARC );
 
  337                        shape->SetStart( 
ScalePos( aStart ) );
 
  340                        shape->SetFilled( aClosed );
 
  343                        results.emplace_back( std::move( shape ) );
 
  351                    addArc( { 
end.x - cr, start.
y }, { 
end.x, start.
y - cr },
 
  352                            { 
end.x - cr, start.
y - cr } );
 
  355                            { 
end.x - cr, 
end.y + cr } );
 
  357                    addArc( { start.
x + cr, 
end.y }, { start.
x, 
end.y + cr },
 
  358                            { start.
x + cr, 
end.y + cr } );
 
  360                    addArc( { start.
x, start.
y - cr }, { start.
x + cr, start.
y },
 
  361                            { start.
x + cr, start.
y - cr } );
 
  364            else if( str == wxS( 
"ARC" ) || str == wxS( 
"CARC" ) )
 
  367                double   angle = polyData.at( ++i ).get<
double>() / ( aInFill ? 10 : 1 );
 
  368                end.x = ( polyData.at( ++i ) );
 
  369                end.y = ( polyData.at( ++i ) );
 
  371                std::unique_ptr<PCB_SHAPE> shape =
 
  372                        std::make_unique<PCB_SHAPE>( aContainer, 
SHAPE_T::ARC );
 
  376                    shape->SetStart( 
ScalePos( prevPt ) );
 
  382                    shape->SetEnd( 
ScalePos( prevPt ) );
 
  388                double   ha = angle / 2;
 
  389                double   hd = 
delta.EuclideanNorm() / 2;
 
  390                double   cdist = hd / tan( 
DEG2RAD( ha ) );
 
  394                shape->SetFilled( aClosed );
 
  396                results.emplace_back( std::move( shape ) );
 
  400            else if( str == wxS( 
"L" ) )
 
  405                while( i < polyData.size() - 2 && polyData.at( i + 1 ).is_number() )
 
  408                    pt.
x = ( polyData.at( ++i ) );
 
  409                    pt.
y = ( polyData.at( ++i ) );
 
  418                    std::unique_ptr<PCB_SHAPE> shape =
 
  421                    wxASSERT( 
chain.PointCount() > 2 );
 
  423                    if( 
chain.PointCount() > 2 )
 
  425                        chain.SetClosed( 
true );
 
  426                        shape->SetFilled( 
true );
 
  427                        shape->SetPolyShape( 
chain );
 
  429                        results.emplace_back( std::move( shape ) );
 
  434                    for( 
int s = 0; s < 
chain.SegmentCount(); s++ )
 
  438                        std::unique_ptr<PCB_SHAPE> shape =
 
  441                        shape->SetStart( seg.
A );
 
  442                        shape->SetEnd( seg.
B );
 
  444                        results.emplace_back( std::move( shape ) );
 
  449        else if( val.is_number() )
 
  451            prevPt.
x = ( polyData.at( i ) );
 
  452            prevPt.
y = ( polyData.at( ++i ) );
 
 
  731                                                     const wxString&                    aFpUuid,
 
  732                                                     const std::vector<nlohmann::json>& aLines )
 
  734    std::unique_ptr<FOOTPRINT> footprintPtr = std::make_unique<FOOTPRINT>( 
m_board );
 
  735    FOOTPRINT*                 footprint = footprintPtr.get();
 
  738    const int      defaultTextThickness( 
pcbIUScale.mmToIU( 0.15 ) );
 
  742        field->SetTextSize( defaultTextSize );
 
  743        field->SetTextThickness( defaultTextThickness );
 
  746    for( 
const nlohmann::json& line : aLines )
 
  748        if( line.size() == 0 )
 
  751        wxString type = line.at( 0 );
 
  753        if( type == wxS( 
"POLY" ) || type == wxS( 
"PAD" ) || type == wxS( 
"FILL" )
 
  754            || type == wxS( 
"ATTR" ) )
 
  756            wxString uuid = line.at( 1 );
 
  763            wxString     netname = line.at( 3 );
 
  764            int          layer = line.at( 4 ).get<
int>();
 
  767            if( type == wxS( 
"POLY" ) )
 
  769                double         thickness = ( line.at( 5 ) );
 
  770                nlohmann::json polyData = line.at( 6 );
 
  772                std::vector<std::unique_ptr<PCB_SHAPE>> results =
 
  773                        ParsePoly( footprint, polyData, 
false, 
false );
 
  775                for( 
auto& shape : results )
 
  777                    shape->SetLayer( klayer );
 
  778                    shape->SetWidth( 
ScaleSize( thickness ) );
 
  783            else if( type == wxS( 
"PAD" ) )
 
  785                std::unique_ptr<PAD> 
pad = 
createPAD( footprint, line );
 
  789            else if( type == wxS( 
"FILL" ) )
 
  791                int          layer = line.at( 4 ).get<
int>();
 
  794                double width = line.at( 5 );
 
  796                nlohmann::json polyDataList = line.at( 7 );
 
  798                if( !polyDataList.is_null() && !polyDataList.empty() )
 
  800                    if( !polyDataList.at( 0 ).is_array() )
 
  801                        polyDataList = nlohmann::json::array( { polyDataList } );
 
  803                    std::vector<SHAPE_LINE_CHAIN> contours;
 
  804                    for( nlohmann::json& polyData : polyDataList )
 
  809                        contours.push_back( contour );
 
  819                    std::unique_ptr<PCB_GROUP> 
group;
 
  822                        group = std::make_unique<PCB_GROUP>( footprint );
 
  828                        std::unique_ptr<PCB_SHAPE> shape =
 
  831                        shape->SetFilled( 
true );
 
  832                        shape->SetPolyShape( poly );
 
  833                        shape->SetLayer( klayer );
 
  834                        shape->SetWidth( 0 );
 
  837                            group->AddItem( shape.get() );
 
  846            else if( type == wxS( 
"ATTR" ) )
 
  850                if( attr.
key == wxS( 
"Designator" ) )
 
  854        else if( type == wxS( 
"REGION" ) )
 
  856            wxString uuid = line.at( 1 );
 
  863            int          layer = line.at( 3 ).get<
int>();
 
  866            double         width = line.at( 4 );
 
  867            std::set<int>  flags = line.at( 5 );
 
  868            nlohmann::json polyDataList = line.at( 6 );
 
  870            for( nlohmann::json& polyData : polyDataList )
 
  874                std::vector<std::unique_ptr<PCB_SHAPE>> results =
 
  875                        ParsePoly( 
nullptr, polyData, 
true, 
false );
 
  877                for( 
auto& shape : results )
 
  879                    shape->SetFilled( 
true );
 
  886                std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( footprint );
 
  888                zone->SetIsRuleArea( 
true );
 
  889                zone->SetDoNotAllowFootprints( !!flags.count( 2 ) );
 
  890                zone->SetDoNotAllowZoneFills( !!flags.count( 7 ) || !!flags.count( 6 )
 
  891                                              || !!flags.count( 8 ) );
 
  892                zone->SetDoNotAllowPads( !!flags.count( 7 ) );
 
  893                zone->SetDoNotAllowTracks( !!flags.count( 7 ) || !!flags.count( 5 ) );
 
  894                zone->SetDoNotAllowVias( !!flags.count( 7 ) );
 
  896                zone->SetLayer( klayer );
 
  897                zone->Outline()->Append( polySet );
 
  904    if( aProject.is_object() && aProject.contains( 
"devices" ) )
 
  906        std::map<wxString, EASYEDAPRO::PRJ_DEVICE> devicesMap = aProject.at( 
"devices" );
 
  907        std::map<wxString, wxString>               compAttrs;
 
  909        for( 
auto& [devUuid, devData] : devicesMap )
 
  911            if( 
auto fp = 
get_opt( devData.attributes, 
"Footprint" ) )
 
  915                    compAttrs = devData.attributes;
 
  921        wxString modelUuid, modelTitle, modelTransform;
 
  923        modelUuid = 
get_def( compAttrs, 
"3D Model", 
"" );
 
  924        modelTitle = 
get_def( compAttrs, 
"3D Model Title", modelUuid );
 
  925        modelTransform = 
get_def( compAttrs, 
"3D Model Transform", 
"" );
 
  931    std::vector<PCB_SHAPE*>                 edgeShapes;
 
  936            edgeShapes.push_back( 
static_cast<PCB_SHAPE*
>( item ) );
 
  947        std::unique_ptr<PCB_SHAPE> shape =
 
  953        shape->SetEnd( bbox.
GetEnd() );
 
  958    bool hasFabRef = 
false;
 
  964            if( 
static_cast<PCB_TEXT*
>( item )->GetText() == wxT( 
"${REFERENCE}" ) )
 
  976        int c_refTextThickness = 
pcbIUScale.mmToIU( 0.1 ); 
 
  977        std::unique_ptr<PCB_TEXT> refText = std::make_unique<PCB_TEXT>( footprint );
 
  979        refText->SetLayer( 
F_Fab );
 
  980        refText->SetTextSize( 
VECTOR2I( c_refTextSize, c_refTextSize ) );
 
  981        refText->SetTextThickness( c_refTextThickness );
 
  982        refText->SetText( wxT( 
"${REFERENCE}" ) );
 
  987    return footprintPtr.release();
 
 
  992        BOARD* aBoard, 
const nlohmann::json& aProject,
 
  993        std::map<wxString, std::unique_ptr<FOOTPRINT>>&    aFootprintMap,
 
  994        const std::map<wxString, EASYEDAPRO::BLOB>&        aBlobMap,
 
  995        const std::multimap<wxString, EASYEDAPRO::POURED>& aPouredMap,
 
  996        const std::vector<nlohmann::json>& aLines, 
const wxString& aFpLibName )
 
  998    std::map<wxString, std::vector<nlohmann::json>> componentLines;
 
  999    std::map<wxString, std::vector<nlohmann::json>> ruleLines;
 
 1001    std::multimap<wxString, EASYEDAPRO::POURED> boardPouredMap = aPouredMap;
 
 1002    std::map<wxString, ZONE*>                   poursToFill;
 
 1006    for( 
const nlohmann::json& line : aLines )
 
 1008        if( line.size() == 0 )
 
 1011        wxString type = line.at( 0 );
 
 1013        if( type == wxS( 
"LAYER" ) )
 
 1015            int          layer = line.at( 1 );
 
 1018            wxString layerType = line.at( 2 );
 
 1019            wxString layerName = line.at( 3 );
 
 1020            int      layerFlag = line.at( 4 );
 
 1022            if( layerFlag != 0 )
 
 1025                blayers.
set( klayer );
 
 1030        else if( type == wxS( 
"NET" ) )
 
 1032            wxString netname = line.at( 1 );
 
 1037        else if( type == wxS( 
"RULE" ) )
 
 1039            wxString       ruleType = line.at( 1 );
 
 1040            wxString       ruleName = line.at( 2 );
 
 1041            int            isDefault = line.at( 3 );
 
 1042            nlohmann::json ruleData = line.at( 4 );
 
 1044            if( ruleType == wxS( 
"3" ) && isDefault ) 
 
 1046                wxString units = ruleData.at( 0 );
 
 1047                double   minVal = ruleData.at( 1 );
 
 1048                double   optVal = ruleData.at( 2 );
 
 1049                double   maxVal = ruleData.at( 3 );
 
 1053            else if( ruleType == wxS( 
"1" ) && isDefault )
 
 1055                wxString       units = ruleData.at( 0 );
 
 1056                nlohmann::json 
table = ruleData.at( 1 );
 
 1058                int minVal = INT_MAX;
 
 1059                for( 
const std::vector<int>& arr : 
table )
 
 1061                    for( 
int val : arr )
 
 1071            ruleLines[ruleType].push_back( line );
 
 1073        else if( type == wxS( 
"POURED" ) )
 
 1075            if( !line.at( 2 ).is_string() )
 
 1079            boardPouredMap.emplace( poured.
parentId, poured );
 
 1081        else if( type == wxS( 
"VIA" ) || type == wxS( 
"LINE" ) || type == wxS( 
"ARC" )
 
 1082                 || type == wxS( 
"POLY" ) || type == wxS( 
"FILL" ) || type == wxS( 
"POUR" ) )
 
 1084            wxString uuid = line.at( 1 );
 
 1091            wxString netname = line.at( 3 );
 
 1093            if( type == wxS( 
"VIA" ) )
 
 1099                double drill = line.at( 7 );
 
 1100                double dia = line.at( 8 );
 
 1102                std::unique_ptr<PCB_VIA> 
via = std::make_unique<PCB_VIA>( aBoard );
 
 1112            else if( type == wxS( 
"LINE" ) )
 
 1114                int          layer = line.at( 4 ).get<
int>();
 
 1118                start.
x = line.at( 5 );
 
 1119                start.
y = line.at( 6 );
 
 1122                end.x = line.at( 7 );
 
 1123                end.y = line.at( 8 );
 
 1125                double width = line.at( 9 );
 
 1127                std::unique_ptr<PCB_TRACK> track = std::make_unique<PCB_TRACK>( aBoard );
 
 1129                track->SetLayer( klayer );
 
 1130                track->SetStart( 
ScalePos( start ) );
 
 1134                track->SetNet( aBoard->
FindNet( netname ) );
 
 1138            else if( type == wxS( 
"ARC" ) )
 
 1140                int          layer = line.at( 4 ).get<
int>();
 
 1144                start.
x = line.at( 5 );
 
 1145                start.
y = line.at( 6 );
 
 1148                end.x = line.at( 7 );
 
 1149                end.y = line.at( 8 );
 
 1151                double angle = line.at( 9 );
 
 1152                double width = line.at( 10 );
 
 1157                double   ha = angle / 2;
 
 1158                double   hd = 
delta.EuclideanNorm() / 2;
 
 1159                double   cdist = hd / tan( 
DEG2RAD( ha ) );
 
 1166                std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( aBoard, &sarc );
 
 1169                arc->SetLayer( klayer );
 
 1170                arc->SetNet( aBoard->
FindNet( netname ) );
 
 1174            else if( type == wxS( 
"FILL" ) )
 
 1176                int          layer = line.at( 4 ).get<
int>();
 
 1179                double width = line.at( 5 );
 
 1181                nlohmann::json polyDataList = line.at( 7 );
 
 1183                if( !polyDataList.at( 0 ).is_array() )
 
 1184                    polyDataList = nlohmann::json::array( { polyDataList } );
 
 1186                std::vector<SHAPE_LINE_CHAIN> contours;
 
 1187                for( nlohmann::json& polyData : polyDataList )
 
 1192                    contours.push_back( contour );
 
 1203                std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
 
 1205                zone->SetNet( aBoard->
FindNet( netname ) );
 
 1206                zone->SetLayer( klayer );
 
 1208                zone->SetFilledPolysList( klayer, zoneFillPoly );
 
 1209                zone->SetAssignedPriority( 500 );
 
 1210                zone->SetIsFilled( 
true );
 
 1211                zone->SetNeedRefill( 
false );
 
 1218            else if( type == wxS( 
"POLY" ) )
 
 1220                int          layer = line.at( 4 );
 
 1223                double         thickness = line.at( 5 );
 
 1224                nlohmann::json polyData = line.at( 6 );
 
 1226                std::vector<std::unique_ptr<PCB_SHAPE>> results =
 
 1227                        ParsePoly( aBoard, polyData, 
false, 
false );
 
 1229                for( 
auto& shape : results )
 
 1231                    shape->SetLayer( klayer );
 
 1232                    shape->SetWidth( 
ScaleSize( thickness ) );
 
 1237            else if( type == wxS( 
"POUR" ) )
 
 1239                int          layer = line.at( 4 ).get<
int>();
 
 1242                double         lineWidth = line.at( 5 ); 
 
 1243                wxString       pourname = line.at( 6 );
 
 1244                int            fillOrder = line.at( 7 ).get<
int>();
 
 1245                nlohmann::json polyDataList = line.at( 8 );
 
 1247                std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
 
 1249                zone->SetNet( aBoard->
FindNet( netname ) );
 
 1250                zone->SetLayer( klayer );
 
 1251                zone->SetAssignedPriority( 500 - fillOrder );
 
 1255                for( nlohmann::json& polyData : polyDataList )
 
 1260                    zone->Outline()->Append( contour );
 
 1263                wxASSERT( zone->Outline()->OutlineCount() == 1 );
 
 1265                poursToFill.emplace( uuid, zone.get() );
 
 1270        else if( type == wxS( 
"TEARDROP" ) )
 
 1272            wxString     uuid = line.at( 1 );
 
 1273            wxString     netname = line.at( 2 );
 
 1274            int          layer = line.at( 3 ).get<
int>();
 
 1277            nlohmann::json polyData = line.at( 4 );
 
 1282            std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
 
 1284            zone->SetNet( aBoard->
FindNet( netname ) );
 
 1285            zone->SetLayer( klayer );
 
 1286            zone->Outline()->Append( contour );
 
 1287            zone->SetFilledPolysList( klayer, contour );
 
 1288            zone->SetNeedRefill( 
false );
 
 1289            zone->SetIsFilled( 
true );
 
 1291            zone->SetAssignedPriority( 600 );
 
 1292            zone->SetLocalClearance( 0 );
 
 1293            zone->SetMinThickness( 0 );
 
 1298        else if( type == wxS( 
"REGION" ) )
 
 1300            wxString uuid = line.at( 1 );
 
 1307            int          layer = line.at( 3 ).get<
int>();
 
 1310            double         width = line.at( 4 );
 
 1311            std::set<int>  flags = line.at( 5 );
 
 1312            nlohmann::json polyDataList = line.at( 6 );
 
 1314            for( nlohmann::json& polyData : polyDataList )
 
 1319                std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( aBoard );
 
 1321                zone->SetIsRuleArea( 
true );
 
 1322                zone->SetDoNotAllowFootprints( !!flags.count( 2 ) );
 
 1323                zone->SetDoNotAllowZoneFills( !!flags.count( 7 ) || !!flags.count( 6 )
 
 1324                                              || !!flags.count( 8 ) );
 
 1325                zone->SetDoNotAllowPads( !!flags.count( 7 ) );
 
 1326                zone->SetDoNotAllowTracks( !!flags.count( 7 ) || !!flags.count( 5 ) );
 
 1327                zone->SetDoNotAllowVias( !!flags.count( 7 ) );
 
 1329                zone->SetLayer( klayer );
 
 1330                zone->Outline()->Append( contour );
 
 1335        else if( type == wxS( 
"PAD" ) )
 
 1337            wxString netname = line.at( 3 );
 
 1339            std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>( aBoard );
 
 1340            std::unique_ptr<PAD>       
pad = 
createPAD( footprint.get(), line );
 
 1351            footprint->SetPosition( pos );
 
 1352            footprint->SetOrientation( orient );
 
 1354            wxString fpName = wxS( 
"Pad_" ) + line.at( 1 ).get<wxString>();
 
 1357            footprint->SetFPID( fpID );
 
 1358            footprint->Reference().SetVisible( 
true );
 
 1359            footprint->Value().SetVisible( 
true );
 
 1360            footprint->AutoPositionFields();
 
 1364        else if( type == wxS( 
"IMAGE" ) )
 
 1366            wxString uuid = line.at( 1 );
 
 1373            int          layer = line.at( 3 ).get<
int>();
 
 1376            VECTOR2D start( line.at( 4 ), line.at( 5 ) );
 
 1377            VECTOR2D size( line.at( 6 ), line.at( 7 ) );
 
 1379            double         angle = line.at( 8 ); 
 
 1380            int            mirror = line.at( 9 );
 
 1381            nlohmann::json polyDataList = line.at( 10 );
 
 1384            std::vector<SHAPE_LINE_CHAIN> contours;
 
 1385            for( nlohmann::json& polyData : polyDataList )
 
 1390                contours.push_back( contour );
 
 1402                for( 
int i = 0; i < contour.PointCount(); i++ )
 
 1413            std::unique_ptr<PCB_GROUP> 
group;
 
 1416                group = std::make_unique<PCB_GROUP>( aBoard );
 
 1422                std::unique_ptr<PCB_SHAPE> shape =
 
 1425                shape->SetFilled( 
true );
 
 1426                shape->SetPolyShape( poly );
 
 1427                shape->SetLayer( klayer );
 
 1428                shape->SetWidth( 0 );
 
 1438                    shape->Mirror( 
ScalePos( start ), flipDirection );
 
 1442                    group->AddItem( shape.get() );
 
 1450        else if( type == wxS( 
"OBJ" ) )
 
 1453            wxString mimeType, base64Data;
 
 1457            if( !line.at( 3 ).is_number() )
 
 1460            int          layer = line.at( 3 ).get<
int>();
 
 1463            start = 
VECTOR2D( line.at( 5 ), line.at( 6 ) );
 
 1464            size = 
VECTOR2D( line.at( 7 ), line.at( 8 ) );
 
 1465            angle = line.at( 9 );
 
 1466            flipped = line.at( 10 );
 
 1468            wxString imageUrl = line.at( 11 );
 
 1470            if( imageUrl.BeforeFirst( 
':' ) == wxS( 
"blob" ) )
 
 1472                wxString objectId = imageUrl.AfterLast( 
':' );
 
 1474                if( 
auto blob = 
get_opt( aBlobMap, objectId ) )
 
 1476                    wxString blobUrl = blob->url;
 
 1478                    if( blobUrl.BeforeFirst( 
':' ) == wxS( 
"data" ) )
 
 1480                        wxArrayString paramsArr =
 
 1481                                wxSplit( blobUrl.AfterFirst( 
':' ).BeforeFirst( 
',' ), 
';', 
'\0' );
 
 1483                        base64Data = blobUrl.AfterFirst( 
',' );
 
 1485                        if( paramsArr.size() > 0 )
 
 1486                            mimeType = paramsArr[0];
 
 1494            if( mimeType.empty() || base64Data.empty() )
 
 1497            wxMemoryBuffer buf = wxBase64Decode( base64Data );
 
 1499            if( mimeType == wxS( 
"image/svg+xml" ) )
 
 1505                VECTOR2D kcenter = kstart + ksize / 2;
 
 1507                std::unique_ptr<PCB_REFERENCE_IMAGE> bitmap =
 
 1508                        std::make_unique<PCB_REFERENCE_IMAGE>( aBoard, kcenter, klayer );
 
 1511                wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
 
 1512                                              & ~wxImage::Load_Verbose );
 
 1524                        int x = bitmap->GetPosition().x;
 
 1535        else if( type == wxS( 
"STRING" ) )
 
 1537            wxString uuid = line.at( 1 );
 
 1544            int          layer = line.at( 3 ).get<
int>();
 
 1548            wxString 
string = line.at( 6 );
 
 1549            wxString font = line.at( 7 );
 
 1551            double height = line.at( 8 );
 
 1552            double strokew = line.at( 9 );
 
 1554            int    align = line.at( 12 );
 
 1555            double angle = line.at( 13 );
 
 1556            int    inverted = line.at( 14 );
 
 1557            int    mirror = line.at( 16 );
 
 1561            text->SetText( 
string );
 
 1562            text->SetLayer( klayer );
 
 1564            text->SetIsKnockout( inverted );
 
 1568            if( font != wxS( 
"default" ) )
 
 1581                text->SetMirrored( 
true );
 
 1582                text->SetTextAngleDegrees( -angle );
 
 1586                text->SetTextAngleDegrees( angle );
 
 1591        else if( type == wxS( 
"COMPONENT" ) )
 
 1593            wxString compId = line.at( 1 );
 
 1594            componentLines[compId].push_back( line );
 
 1596        else if( type == wxS( 
"ATTR" ) )
 
 1598            wxString compId = line.at( 3 );
 
 1599            componentLines[compId].push_back( line );
 
 1601        else if( type == wxS( 
"PAD_NET" ) )
 
 1603            wxString compId = line.at( 1 );
 
 1604            componentLines[compId].push_back( line );
 
 1608    for( 
auto const& [compId, lines] : componentLines )
 
 1611        wxString                     fpIdOverride;
 
 1612        wxString                     fpDesignator;
 
 1613        std::map<wxString, wxString> localCompAttribs;
 
 1615        for( 
auto& line : lines )
 
 1617            if( line.size() == 0 )
 
 1620            wxString type = line.at( 0 );
 
 1622            if( type == wxS( 
"COMPONENT" ) )
 
 1624                localCompAttribs = line.at( 7 );
 
 1626            else if( type == wxS( 
"ATTR" ) )
 
 1630                if( attr.
key == wxS( 
"Device" ) )
 
 1631                    deviceId = attr.
value;
 
 1633                else if( attr.
key == wxS( 
"Footprint" ) )
 
 1634                    fpIdOverride = attr.
value;
 
 1636                else if( attr.
key == wxS( 
"Designator" ) )
 
 1637                    fpDesignator = attr.
value;
 
 1641        if( deviceId.empty() )
 
 1644        nlohmann::json compAttrs = aProject.at( 
"devices" ).at( deviceId ).at( 
"attributes" );
 
 1648        if( !fpIdOverride.IsEmpty() )
 
 1649            fpId = fpIdOverride;
 
 1651            fpId = compAttrs.at( 
"Footprint" ).get<wxString>();
 
 1653        auto it = aFootprintMap.find( fpId );
 
 1654        if( it == aFootprintMap.end() )
 
 1656            wxLogError( 
"Footprint of '%s' with uuid '%s' not found.", fpDesignator, fpId );
 
 1660        std::unique_ptr<FOOTPRINT>& footprintOrig = it->second;
 
 1661        std::unique_ptr<FOOTPRINT>  footprint( 
static_cast<FOOTPRINT*
>( footprintOrig->Clone() ) );
 
 1663        wxString modelUuid, modelTitle, modelTransform;
 
 1665        if( 
auto val = 
get_opt( localCompAttribs, 
"3D Model" ) )
 
 1668            modelUuid = compAttrs.value<wxString>( 
"3D Model", 
"" );
 
 1670        if( 
auto val = 
get_opt( localCompAttribs, 
"3D Model Title" ) )
 
 1671            modelTitle = val->Trim();
 
 1673            modelTitle = compAttrs.value<wxString>( 
"3D Model Title", modelUuid ).Trim();
 
 1675        if( 
auto val = 
get_opt( localCompAttribs, 
"3D Model Transform" ) )
 
 1676            modelTransform = *val;
 
 1678            modelTransform = compAttrs.value<wxString>( 
"3D Model Transform", 
"" );
 
 1682        footprint->SetParent( aBoard );
 
 1684        for( 
auto& line : lines )
 
 1686            if( line.size() == 0 )
 
 1689            wxString type = line.at( 0 );
 
 1691            if( type == wxS( 
"COMPONENT" ) )
 
 1693                int          layer = line.at( 3 );
 
 1698                double                       orient = line.at( 6 );
 
 1701                if( klayer == 
B_Cu )
 
 1704                footprint->SetOrientationDegrees( orient );
 
 1707            else if( type == wxS( 
"ATTR" ) )
 
 1715                if( attr.
key == wxS( 
"Designator" ) )
 
 1717                    if( attr.
key == wxS( 
"Designator" ) )
 
 1727                    if( attr.
fontName != wxS( 
"default" ) )
 
 1756            else if( type == wxS( 
"PAD_NET" ) )
 
 1758                wxString padNumber = line.at( 2 );
 
 1759                wxString padNet = line.at( 3 );
 
 1761                PAD* 
pad = footprint->FindPadByNumber( padNumber );
 
 1779        for( 
auto& [uuid, zone] : poursToFill )
 
 1784            auto range = boardPouredMap.equal_range( uuid );
 
 1785            for( 
auto& it = range.first; it != range.second; ++it )
 
 1788                int                       unki = poured.
unki;
 
 1792                for( 
int dataId = 0; dataId < poured.
polyData.size(); dataId++ )
 
 1794                    const nlohmann::json& fillData = poured.
polyData[dataId];
 
 1795                    const double          ptScale = 10;
 
 1800                    for( 
int i = 0; i < contour.
PointCount(); i++ )
 
 1813                            thisPoly.
Append( simple );
 
 1822                        const int thermalWidth = 
pcbIUScale.mmToIU( 0.2 ); 
 
 1824                        for( 
int segId = 0; segId < contour.
SegmentCount(); segId++ )
 
 1834                fillPolySet.
Append( thisPoly );
 
 1841                const int strokeWidth = 
pcbIUScale.MilsToIU( 8 ); 
 
 1850                zone->SetFilledPolysList( zone->GetFirstLayer(), fillPolySet );
 
 1851                zone->SetNeedRefill( 
false );
 
 1852                zone->SetIsFilled( 
true );
 
 1858    std::vector<PCB_SHAPE*> shapes;
 
 1866            shapes.push_back( 
static_cast<PCB_SHAPE*
>( item ) );
 
 1881    offset.
x = 
KiROUND( offset.
x / alignGrid ) * alignGrid;
 
 1882    offset.
y = 
KiROUND( offset.
y / alignGrid ) * alignGrid;
 
 1884    aBoard->
Move( offset );