From 089b7afacf64ba7e904afb9ee41977b51bf47145 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Mon, 15 Feb 2021 16:44:58 -0500 Subject: [PATCH] Eeschema: Eagle schematic plugin parser improvements. * Fix multi line text alignment. * Parse schematic frame objects and convert them to lines. * Make implicit global labels normal size so they can easily be seen. * Move sheet fields to a more sensible position. * Parse schematic symbol instances before wires so that the implicit power connections can properly be tested. This will be used at a later time. * Scale label text size down to allow for differences in label offset and graphical items. --- common/plugins/eagle/eagle_parser.cpp | 86 +++++-- common/plugins/eagle/eagle_parser.h | 38 ++- .../sch_plugins/eagle/sch_eagle_plugin.cpp | 233 +++++++++++++----- eeschema/sch_plugins/eagle/sch_eagle_plugin.h | 7 + 4 files changed, 276 insertions(+), 88 deletions(-) diff --git a/common/plugins/eagle/eagle_parser.cpp b/common/plugins/eagle/eagle_parser.cpp index 47f3451a07..506c708a52 100644 --- a/common/plugins/eagle/eagle_parser.cpp +++ b/common/plugins/eagle/eagle_parser.cpp @@ -2,8 +2,9 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 2012-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2017 CERN. + * * @author Alejandro García Montoro * * This program is free software; you can redistribute it and/or @@ -59,17 +60,21 @@ OPTIONAL_XML_ATTRIBUTE::OPTIONAL_XML_ATTRIBUTE( wxString aData ) ECOORD::ECOORD( const wxString& aValue, enum ECOORD::EAGLE_UNIT aUnit ) { - // this array is used to adjust the fraction part value basing on the number of digits in the fraction + // This array is used to adjust the fraction part value basing on the number of digits + // in the fraction. constexpr int DIVIDERS[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 }; constexpr unsigned int DIVIDERS_MAX_IDX = sizeof( DIVIDERS ) / sizeof( DIVIDERS[0] ) - 1; int integer, fraction, pre_fraction, post_fraction; - // the following check is needed to handle correctly negative fractions where the integer part == 0 + // The following check is needed to handle correctly negative fractions where the integer + // part == 0. bool negative = ( aValue[0] == '-' ); - // %n is used to find out how many digits contains the fraction part, e.g. 0.001 contains 3 digits - int ret = sscanf( aValue.c_str(), "%d.%n%d%n", &integer, &pre_fraction, &fraction, &post_fraction ); + // %n is used to find out how many digits contains the fraction part, e.g. 0.001 contains 3 + // digits. + int ret = sscanf( aValue.c_str(), "%d.%n%d%n", &integer, &pre_fraction, &fraction, + &post_fraction ); if( ret == 0 ) throw XML_PARSER_ERROR( "Invalid coordinate" ); @@ -82,7 +87,8 @@ ECOORD::ECOORD( const wxString& aValue, enum ECOORD::EAGLE_UNIT aUnit ) { int digits = post_fraction - pre_fraction; - // adjust the number of digits if necessary as we cannot handle anything smaller than nanometers (rounding) + // adjust the number of digits if necessary as we cannot handle anything smaller than + // nanometers (rounding). if( (unsigned) digits > DIVIDERS_MAX_IDX ) { int diff = digits - DIVIDERS_MAX_IDX; @@ -204,8 +210,8 @@ ECOORD Convert( const wxString& aCoord ) /** - * Function parseRequiredAttribute - * parsese the aAttribute of the XML node aNode. + * Parse \a aAttribute of the XML node \a aNode. + * * @param aNode is the node whose attribute will be parsed. * @param aAttribute is the attribute that will be parsed. * @throw XML_PARSER_ERROR - exception thrown if the required attribute is missing @@ -224,12 +230,12 @@ T parseRequiredAttribute( wxXmlNode* aNode, const wxString& aAttribute ) /** - * Function parseOptionalAttribute - * parses the aAttribute of the XML node aNode. + * Parse option \a aAttribute of the XML node \a aNode. + * * @param aNode is the node whose attribute will be parsed. * @param aAttribute is the attribute that will be parsed. * @return OPTIONAL_XML_ATTRIBUTE - an optional XML attribute, parsed as the specified type if - * found. + * found. */ template OPTIONAL_XML_ATTRIBUTE parseOptionalAttribute( wxXmlNode* aNode, const wxString& aAttribute ) @@ -610,6 +616,43 @@ wxSize ETEXT::ConvertSize() const } +EFRAME::EFRAME( wxXmlNode* aFrameNode ) +{ + /* + * + * + */ + border_left = true; + border_top = true; + border_right = true; + border_bottom = true; + + x1 = parseRequiredAttribute( aFrameNode, "x1" ); + y1 = parseRequiredAttribute( aFrameNode, "y1" ); + x2 = parseRequiredAttribute( aFrameNode, "x2" ); + y2 = parseRequiredAttribute( aFrameNode, "y2" ); + columns = parseRequiredAttribute( aFrameNode, "columns" ); + rows = parseRequiredAttribute( aFrameNode, "rows" ); + layer = parseRequiredAttribute( aFrameNode, "layer" ); + border_left = parseOptionalAttribute( aFrameNode, "border-left" ); + border_top = parseOptionalAttribute( aFrameNode, "border-top" ); + border_right = parseOptionalAttribute( aFrameNode, "border-right" ); + border_bottom = parseOptionalAttribute( aFrameNode, "border-bottom" ); +} + + EPAD_COMMON::EPAD_COMMON( wxXmlNode* aPad ) { // #REQUIRED says DTD, throw exception if not found @@ -753,7 +796,8 @@ EPOLYGON::EPOLYGON( wxXmlNode* aPolygon ) isolate %Dimension; #IMPLIED -- only in or context -- orphans %Bool; "no" -- only in context -- thermals %Bool; "yes" -- only in context -- - rank %Int; "0" -- 1..6 in context, 0 or 7 in context -- + rank %Int; "0" -- 1..6 in context, 0 or 7 in + context -- > */ @@ -996,12 +1040,12 @@ ECONNECT::ECONNECT( wxXmlNode* aConnect ) EDEVICE::EDEVICE( wxXmlNode* aDevice ) { /* - - -*/ + + + */ name = parseRequiredAttribute( aDevice, "name" ); opt_wxString pack = parseOptionalAttribute( aDevice, "package" ); @@ -1026,13 +1070,13 @@ EDEVICE::EDEVICE( wxXmlNode* aDevice ) EDEVICE_SET::EDEVICE_SET( wxXmlNode* aDeviceSet ) { /* - - + - */ + */ name = parseRequiredAttribute(aDeviceSet, "name"); prefix = parseOptionalAttribute( aDeviceSet, "prefix" ); diff --git a/common/plugins/eagle/eagle_parser.h b/common/plugins/eagle/eagle_parser.h index 673ca4589f..e44402da43 100644 --- a/common/plugins/eagle/eagle_parser.h +++ b/common/plugins/eagle/eagle_parser.h @@ -4,6 +4,7 @@ * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2012-2021 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2017 CERN + * * @author Alejandro García Montoro * * This program is free software; you can redistribute it and/or @@ -69,9 +70,9 @@ static inline wxXmlNode* getChildrenNodes( NODE_MAP& aMap, const wxString& aName struct XML_PARSER_ERROR : std::runtime_error { /** - * Constructor XML_PARSER_ERROR - * build an XML error by just calling its parent class constructor, std::runtime_error, with + * Build an XML error by just calling its parent class constructor, std::runtime_error, with * the passed message. + * * @param aMessage is an explanatory error message. */ XML_PARSER_ERROR( const wxString& aMessage ) noexcept : @@ -669,6 +670,27 @@ struct ETEXT }; +/** + * Parse an Eagle frame element. + */ +struct EFRAME +{ + ECOORD x1; + ECOORD y1; + ECOORD x2; + ECOORD y2; + int columns; + int rows; + int layer; + opt_bool border_left; + opt_bool border_top; + opt_bool border_right; + opt_bool border_bottom; + + EFRAME( wxXmlNode* aFrameNode ); +}; + + /// Structure holding common properties for through-hole and SMD pads struct EPAD_COMMON { @@ -997,12 +1019,12 @@ struct ECONNECT struct EDEVICE { /* - - -*/ + * + * + */ wxString name; opt_wxString package; diff --git a/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp b/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp index 4ab0de05ad..b1f1c68ba6 100644 --- a/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp +++ b/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp @@ -195,7 +195,6 @@ void SCH_EAGLE_PLUGIN::loadLayerDefs( wxXmlNode* aLayers ) * */ - if( elayer.name == "Nets" ) { m_layerMap[elayer.number] = LAYER_WIRE; @@ -515,13 +514,14 @@ void SCH_EAGLE_PLUGIN::countNets( wxXmlNode* aSchematicNode ) { // Map all children into a readable dictionary NODE_MAP schematicChildren = MapChildren( aSchematicNode ); - // Loop through all the sheets + // Loop through all the sheets wxXmlNode* sheetNode = getChildrenNodes( schematicChildren, "sheets" ); while( sheetNode ) { NODE_MAP sheetChildren = MapChildren( sheetNode ); + // Loop through all nets // From the DTD: "Net is an electrical connection in a schematic." wxXmlNode* netNode = getChildrenNodes( sheetChildren, "nets" ); @@ -547,10 +547,10 @@ void SCH_EAGLE_PLUGIN::countNets( wxXmlNode* aSchematicNode ) void SCH_EAGLE_PLUGIN::loadSchematic( wxXmlNode* aSchematicNode ) { // Map all children into a readable dictionary - NODE_MAP schematicChildren = MapChildren( aSchematicNode ); - auto partNode = getChildrenNodes( schematicChildren, "parts" ); - auto libraryNode = getChildrenNodes( schematicChildren, "libraries" ); - auto sheetNode = getChildrenNodes( schematicChildren, "sheets" ); + NODE_MAP schematicChildren = MapChildren( aSchematicNode ); + wxXmlNode* partNode = getChildrenNodes( schematicChildren, "parts" ); + wxXmlNode* libraryNode = getChildrenNodes( schematicChildren, "libraries" ); + wxXmlNode* sheetNode = getChildrenNodes( schematicChildren, "sheets" ); if( !partNode || !libraryNode || !sheetNode ) return; @@ -630,7 +630,6 @@ void SCH_EAGLE_PLUGIN::loadSchematic( wxXmlNode* aSchematicNode ) } } - // Handle the missing component units that need to be instantiated // to create the missing implicit connections @@ -716,6 +715,17 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode, int aSheetIndex ) filenameField.SetText( fn ); wxFileName fileName( fn ); m_currentSheet->GetScreen()->SetFileName( fileName.GetFullPath() ); + m_currentSheet->AutoplaceFields( m_currentSheet->GetScreen(), true ); + + + // Loop through all of the symbol instances. + wxXmlNode* instanceNode = getChildrenNodes( sheetChildren, "instances" ); + + while( instanceNode ) + { + loadInstance( instanceNode ); + instanceNode = instanceNode->GetNext(); + } // Loop through all buses // From the DTD: "Buses receive names which determine which signals they include. @@ -755,15 +765,6 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode, int aSheetIndex ) adjustNetLabels(); // needs to be called before addBusEntries() addBusEntries(); - // Loop through all instances - wxXmlNode* instanceNode = getChildrenNodes( sheetChildren, "instances" ); - - while( instanceNode ) - { - loadInstance( instanceNode ); - instanceNode = instanceNode->GetNext(); - } - /* moduleinst is a design block definition and is an EagleCad 8 feature, * * // Loop through all moduleinsts @@ -790,6 +791,15 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode, int aSheetIndex ) { m_currentSheet->GetScreen()->Append( loadWire( plainNode ) ); } + else if( nodeName == "frame" ) + { + std::vector lines; + + loadFrame( plainNode, lines ); + + for( SCH_LINE* line : lines ) + m_currentSheet->GetScreen()->Append( line ); + } plainNode = plainNode->GetNext(); } @@ -845,6 +855,41 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode, int aSheetIndex ) } +void SCH_EAGLE_PLUGIN::loadFrame( wxXmlNode* aFrameNode, std::vector& aLines ) +{ + EFRAME eframe( aFrameNode ); + + wxPoint corner1( eframe.x1.ToSchUnits(), -eframe.y1.ToSchUnits() ); + wxPoint corner3( eframe.x2.ToSchUnits(), -eframe.y2.ToSchUnits() ); + wxPoint corner2( corner3.x, corner1.y ); + wxPoint corner4( corner1.x, corner3.y ); + + SCH_LINE* line = new SCH_LINE(); + line->SetLineStyle( PLOT_DASH_TYPE::SOLID ); + line->SetStartPoint( corner1 ); + line->SetEndPoint( corner2 ); + aLines.push_back( line ); + + line = new SCH_LINE(); + line->SetLineStyle( PLOT_DASH_TYPE::SOLID ); + line->SetStartPoint( corner2 ); + line->SetEndPoint( corner3 ); + aLines.push_back( line ); + + line = new SCH_LINE(); + line->SetLineStyle( PLOT_DASH_TYPE::SOLID ); + line->SetStartPoint( corner3 ); + line->SetEndPoint( corner4 ); + aLines.push_back( line ); + + line = new SCH_LINE(); + line->SetLineStyle( PLOT_DASH_TYPE::SOLID ); + line->SetStartPoint( corner4 ); + line->SetEndPoint( corner1 ); + aLines.push_back( line ); +} + + void SCH_EAGLE_PLUGIN::loadSegments( wxXmlNode* aSegmentsNode, const wxString& netName, const wxString& aNetClass ) { @@ -937,8 +982,9 @@ void SCH_EAGLE_PLUGIN::loadSegments( segmentAttribute = segmentAttribute->GetNext(); } - // Add a small label to the net segment if it hasn't been labeled already - // this preserves the named net feature of Eagle schematics. + // Add a small label to the net segment if it hasn't been labeled already or is not + // connect to a power symbol with a pin on the same net. This preserves the named net + // feature of Eagle schematics. if( !labelled && firstWire ) { std::unique_ptr label; @@ -953,7 +999,7 @@ void SCH_EAGLE_PLUGIN::loadSegments( { label->SetPosition( firstWire->GetStartPoint() ); label->SetText( escapeName( netName ) ); - label->SetTextSize( wxSize( Mils2iu( 10 ), Mils2iu( 10 ) ) ); + label->SetTextSize( wxSize( Mils2iu( 40 ), Mils2iu( 40 ) ) ); label->SetLabelSpinStyle( LABEL_SPIN_STYLE::LEFT ); screen->Append( label.release() ); } @@ -1012,14 +1058,24 @@ SCH_TEXT* SCH_EAGLE_PLUGIN::loadLabel( wxXmlNode* aLabelNode, const wxString& aN bool global = m_netCounts[aNetName] > 1; std::unique_ptr label; + wxSize textSize; + if( global ) + { label = std::make_unique(); + textSize = wxSize( KiROUND( elabel.size.ToSchUnits() * 0.75 ), + KiROUND( elabel.size.ToSchUnits() * 0.75 ) ); + } else + { label = std::make_unique(); + textSize = wxSize( KiROUND( elabel.size.ToSchUnits() * 0.85 ), + KiROUND( elabel.size.ToSchUnits() * 0.85 ) ); + } label->SetPosition( elabelpos ); label->SetText( escapeName( elabel.netname ) ); - label->SetTextSize( wxSize( elabel.size.ToSchUnits(), elabel.size.ToSchUnits() ) ); + label->SetTextSize( textSize ); label->SetLabelSpinStyle( LABEL_SPIN_STYLE::RIGHT ); if( elabel.rot ) @@ -1514,6 +1570,18 @@ bool SCH_EAGLE_PLUGIN::loadSymbol( wxXmlNode* aSymbolNode, std::unique_ptrAddDrawItem( loadSymbolWire( aPart, currentNode, aGateNumber ) ); } + else if( nodeName == "frame" ) + { + std::vector frameItems; + + loadFrame( currentNode, frameItems ); + + for( LIB_ITEM* item : frameItems ) + { + item->SetParent( aPart.get() ); + aPart->AddDrawItem( item ); + } + } /* * else if( nodeName == "description" ) @@ -1522,9 +1590,6 @@ bool SCH_EAGLE_PLUGIN::loadSymbol( wxXmlNode* aSymbolNode, std::unique_ptrGetNext(); @@ -1568,6 +1633,7 @@ LIB_RECTANGLE* SCH_EAGLE_PLUGIN::loadSymbolRectangle( rectangle->SetEnd( wxPoint( rect.x2.ToSchUnits(), rect.y2.ToSchUnits() ) ); rectangle->SetUnit( aGateNumber ); + // Eagle rectangles are filled by definition. rectangle->SetFillMode( FILL_TYPE::FILLED_SHAPE ); @@ -1667,9 +1733,7 @@ LIB_POLYLINE* SCH_EAGLE_PLUGIN::loadSymbolPolyLine( EPOLYGON epoly( aPolygonNode ); wxXmlNode* vertex = aPolygonNode->GetChildren(); - - - wxPoint pt; + wxPoint pt; while( vertex ) { @@ -1723,26 +1787,20 @@ LIB_PIN* SCH_EAGLE_PLUGIN::loadPin( break; } + pin->SetLength( Mils2iu( 300 ) ); // Default pin length when not defined. + if( aEPin->length ) { wxString length = aEPin->length.Get(); if( length == "short" ) - { pin->SetLength( Mils2iu( 100 ) ); - } else if( length == "middle" ) - { pin->SetLength( Mils2iu( 200 ) ); - } else if( length == "long" ) - { pin->SetLength( Mils2iu( 300 ) ); - } else if( length == "point" ) - { pin->SetLength( Mils2iu( 0 ) ); - } } // emulate the visibility of pin elements @@ -1818,13 +1876,49 @@ LIB_TEXT* SCH_EAGLE_PLUGIN::loadSymbolText( } +void SCH_EAGLE_PLUGIN::loadFrame( wxXmlNode* aFrameNode, std::vector& aItems ) +{ + EFRAME eframe( aFrameNode ); + + wxPoint corner1( eframe.x1.ToSchUnits(), eframe.y1.ToSchUnits() ); + wxPoint corner3( eframe.x2.ToSchUnits(), eframe.y2.ToSchUnits() ); + wxPoint corner2( corner3.x, corner1.y ); + wxPoint corner4( corner1.x, corner3.y ); + + LIB_POLYLINE* lines = new LIB_POLYLINE( nullptr ); + lines->AddPoint( corner1 ); + lines->AddPoint( corner2 ); + lines->AddPoint( corner3 ); + lines->AddPoint( corner4 ); + lines->AddPoint( corner1 ); + aItems.push_back( lines ); +} + + SCH_TEXT* SCH_EAGLE_PLUGIN::loadPlainText( wxXmlNode* aSchText ) { std::unique_ptr schtext = std::make_unique(); ETEXT etext = ETEXT( aSchText ); const wxString& thetext = aSchText->GetNodeContent(); - schtext->SetText( thetext.IsEmpty() ? "\" \"" : escapeName( thetext ) ); + + wxString adjustedText; + wxStringTokenizer tokenizer( thetext, "\r\n" ); + + // Strip the whitespace from both ends of each line. + while( tokenizer.HasMoreTokens() ) + { + wxString tmp = tokenizer.GetNextToken().Trim(); + + tmp = tmp.Trim( false ); + + if( tokenizer.HasMoreTokens() ) + tmp += wxT( "\n" ); + + adjustedText += tmp; + } + + schtext->SetText( adjustedText.IsEmpty() ? "\" \"" : escapeName( adjustedText ) ); schtext->SetPosition( wxPoint( etext.x.ToSchUnits(), -etext.y.ToSchUnits() ) ); loadTextAttributes( schtext.get(), etext ); schtext->SetItalic( false ); @@ -1876,9 +1970,12 @@ void SCH_EAGLE_PLUGIN::adjustNetLabels() // Sort the intersection points to speed up the search process std::sort( m_wireIntersections.begin(), m_wireIntersections.end() ); - auto onIntersection = [&]( const VECTOR2I& aPos ) { - return std::binary_search( m_wireIntersections.begin(), m_wireIntersections.end(), aPos ); - }; + auto onIntersection = + [&]( const VECTOR2I& aPos ) + { + return std::binary_search( m_wireIntersections.begin(), + m_wireIntersections.end(), aPos ); + }; for( auto& segDesc : m_segments ) { @@ -1948,6 +2045,7 @@ bool SCH_EAGLE_PLUGIN::CheckHeader( const wxString& aFileName ) tempFile.Open( aFileName ); wxString firstline; + // read the first line firstline = tempFile.GetFirstLine(); wxString secondline = tempFile.GetNextLine(); @@ -1992,12 +2090,12 @@ void SCH_EAGLE_PLUGIN::addBusEntries() if( bus->GetLayer() != LAYER_BUS ) continue; - wxPoint busstart = bus->GetStartPoint(); wxPoint busend = bus->GetEndPoint(); auto it2 = it1; ++it2; + for( ; it2 != m_currentSheet->GetScreen()->Items().end(); ++it2 ) { SCH_LINE* line = static_cast( *it2 ); @@ -2009,7 +2107,7 @@ void SCH_EAGLE_PLUGIN::addBusEntries() wxPoint linestart = line->GetStartPoint(); wxPoint lineend = line->GetEndPoint(); - // Test for horizontal wire and vertical bus + // Test for horizontal wire and vertical bus if( linestart.y == lineend.y && busstart.x == busend.x ) { if( TestSegmentHit( linestart, busstart, busend, 0 ) ) @@ -2117,7 +2215,8 @@ void SCH_EAGLE_PLUGIN::addBusEntries() lineend + wxPoint( 0, -100 ), busstart, busend, 0 ) ) { SCH_BUS_WIRE_ENTRY* busEntry = - new SCH_BUS_WIRE_ENTRY( lineend + wxPoint( -100, 0 ), true ); + new SCH_BUS_WIRE_ENTRY( lineend + wxPoint( -100, 0 ), + true ); busEntry->SetFlags( IS_NEW ); m_currentSheet->GetScreen()->Append( busEntry ); moveLabels( line, lineend + wxPoint( -100, 0 ) ); @@ -2257,7 +2356,8 @@ void SCH_EAGLE_PLUGIN::addBusEntries() lineend + wxPoint( -100, 0 ), busstart, busend, 0 ) ) { SCH_BUS_WIRE_ENTRY* busEntry = - new SCH_BUS_WIRE_ENTRY( lineend + wxPoint( -100, 0 ), true ); + new SCH_BUS_WIRE_ENTRY( lineend + wxPoint( -100, 0 ), + true ); busEntry->SetFlags( IS_NEW ); m_currentSheet->GetScreen()->Append( busEntry ); moveLabels( line, lineend + wxPoint( 0, -100 ) ); @@ -2371,7 +2471,8 @@ void SCH_EAGLE_PLUGIN::addBusEntries() { if( wirevector.y > 0 ) { - SCH_BUS_WIRE_ENTRY* busEntry = new SCH_BUS_WIRE_ENTRY( linestart, true ); + SCH_BUS_WIRE_ENTRY* busEntry = new SCH_BUS_WIRE_ENTRY( linestart, + true ); busEntry->SetFlags( IS_NEW ); m_currentSheet->GetScreen()->Append( busEntry ); @@ -2552,18 +2653,20 @@ void SCH_EAGLE_PLUGIN::addImplicitConnections( bool pinInUnit = !unit || pin->GetUnit() == unit; // pin belongs to the tested unit // Create a global net label only if there are no other wires/pins attached - if( pinInUnit && !checkConnections( aComponent, pin ) ) + if( pinInUnit ) { - // Create a net label to force the net name on the pin - SCH_GLOBALLABEL* netLabel = new SCH_GLOBALLABEL; - netLabel->SetPosition( aComponent->GetPinPhysicalPosition( pin ) ); - netLabel->SetText( extractNetName( pin->GetName() ) ); - netLabel->SetTextSize( wxSize( Mils2iu( 10 ), Mils2iu( 10 ) ) ); - netLabel->SetLabelSpinStyle( LABEL_SPIN_STYLE::LEFT ); - aScreen->Append( netLabel ); + if( !checkConnections( aComponent, pin ) ) + { + // Create a net label to force the net name on the pin + SCH_GLOBALLABEL* netLabel = new SCH_GLOBALLABEL; + netLabel->SetPosition( aComponent->GetPinPhysicalPosition( pin ) ); + netLabel->SetText( extractNetName( pin->GetName() ) ); + netLabel->SetTextSize( wxSize( Mils2iu( 40 ), Mils2iu( 40 ) ) ); + netLabel->SetLabelSpinStyle( LABEL_SPIN_STYLE::LEFT ); + aScreen->Append( netLabel ); + } } - - else if( !pinInUnit && aUpdateSet ) + else if( aUpdateSet ) { // Found a pin creating implicit connection information in another unit. // Such units will be instantiated if they do not appear in another sheet and @@ -2574,22 +2677,34 @@ void SCH_EAGLE_PLUGIN::addImplicitConnections( } } - if( aUpdateSet ) + if( aUpdateSet && aComponent->GetPartRef()->GetUnitCount() > 1 ) { auto cmpIt = m_missingCmps.find( reference ); - // Set the flag indicating this unit has been processed - if( cmpIt != m_missingCmps.end() ) + // The first unit found has always already been processed. + if( cmpIt == m_missingCmps.end() ) + { + EAGLE_MISSING_CMP& entry = m_missingCmps[reference]; + entry.cmp = aComponent; + entry.units.emplace( unit, false ); + } + else + { + // Set the flag indicating this unit has been processed. cmpIt->second.units[unit] = false; + } - // Save the units that need later processing - else if( !missingUnits.empty() ) + if( !missingUnits.empty() ) // Save the units that need later processing { EAGLE_MISSING_CMP& entry = m_missingCmps[reference]; entry.cmp = aComponent; + // Add units that haven't already been processed. for( int i : missingUnits ) - entry.units.emplace( i, true ); + { + if( entry.units.find( i ) != entry.units.end() ) + entry.units.emplace( i, true ); + } } } } diff --git a/eeschema/sch_plugins/eagle/sch_eagle_plugin.h b/eeschema/sch_plugins/eagle/sch_eagle_plugin.h index 64ed7e6915..cf8dd7cc0e 100644 --- a/eeschema/sch_plugins/eagle/sch_eagle_plugin.h +++ b/eeschema/sch_plugins/eagle/sch_eagle_plugin.h @@ -127,6 +127,7 @@ private: SCH_TEXT* loadLabel( wxXmlNode* aLabelNode, const wxString& aNetName ); SCH_JUNCTION* loadJunction( wxXmlNode* aJunction ); SCH_TEXT* loadPlainText( wxXmlNode* aSchText ); + void loadFrame( wxXmlNode* aFrameNode, std::vector& aLines ); bool loadSymbol( wxXmlNode* aSymbolNode, std::unique_ptr& aPart, EDEVICE* aDevice, int aGateNumber, const wxString& aGateName ); @@ -142,6 +143,7 @@ private: int aGateNumber ); LIB_TEXT* loadSymbolText( std::unique_ptr& aPart, wxXmlNode* aLibText, int aGateNumber ); + void loadFrame( wxXmlNode* aFrameNode, std::vector& aLines ); void loadTextAttributes( EDA_TEXT* aText, const ETEXT& aAttribs ) const; void loadFieldAttributes( LIB_FIELD* aField, const LIB_TEXT* aText ) const; @@ -179,6 +181,8 @@ private: */ void addImplicitConnections( SCH_COMPONENT* aComponent, SCH_SCREEN* aScreen, bool aUpdateSet ); + bool netHasPowerDriver( SCH_LINE* aLine, const wxString& aNetName ) const; + /** * Fix invalid characters in Eagle symbol names. * @@ -244,6 +248,9 @@ private: ///< Segments representing wires for intersection checking std::vector m_segments; + ///< Nets as defined in the sections of an Eagle schematic file. + std::map m_nets; + ///< Positions of pins and wire endings mapped to its parent std::map> m_connPoints; };