diff --git a/common/plugins/altium/altium_parser.cpp b/common/plugins/altium/altium_parser.cpp index f97a2d694e..c8c2f20a9a 100644 --- a/common/plugins/altium/altium_parser.cpp +++ b/common/plugins/altium/altium_parser.cpp @@ -277,6 +277,41 @@ ALTIUM_COMPOUND_FILE::FindStreamSingleLevel( const CFB::COMPOUND_FILE_ENTRY* aEn } +std::map +ALTIUM_COMPOUND_FILE::GetLibSymbols( const CFB::COMPOUND_FILE_ENTRY* aStart ) const +{ + const CFB::COMPOUND_FILE_ENTRY* root = aStart ? aStart : m_reader->GetRootEntry(); + + if( !root ) + return {}; + + std::map folders; + + m_reader->EnumFiles( root, 1, [&]( const CFB::COMPOUND_FILE_ENTRY* tentry, const CFB::utf16string&, int ) -> int + { + wxString dirName = UTF16ToWstring( tentry->name, tentry->nameLen ); + + if( m_reader->IsStream( tentry ) ) + return 0; + + m_reader->EnumFiles( tentry, 1, + [&]( const CFB::COMPOUND_FILE_ENTRY* entry, const CFB::utf16string&, int ) -> int + { + std::wstring fileName = UTF16ToWstring( entry->name, entry->nameLen ); + + if( m_reader->IsStream( entry ) && fileName == L"Data" ) + folders[dirName] = entry; + + return 0; + } ); + + return 0; + } ); + + return folders; +} + + const CFB::COMPOUND_FILE_ENTRY* ALTIUM_COMPOUND_FILE::FindStream( const CFB::COMPOUND_FILE_ENTRY* aStart, const std::vector& aStreamPath ) const @@ -340,11 +375,16 @@ ALTIUM_PARSER::ALTIUM_PARSER( std::unique_ptr& aContent, size_t aSize ) } -std::map ALTIUM_PARSER::ReadProperties() +std::map ALTIUM_PARSER::ReadProperties( + std::function( const std::string& )> handleBinaryData ) { + std::map kv; uint32_t length = Read(); + bool isBinary = ( length & 0xff000000 ) != 0; + + length &= 0x00ffffff; if( length > GetRemainingBytes() ) { @@ -372,6 +412,11 @@ std::map ALTIUM_PARSER::ReadProperties() std::string str = std::string( m_pos, length - ( hasNullByte ? 1 : 0 ) ); m_pos += length; + if( isBinary ) + { + return handleBinaryData( str ); + } + std::size_t token_end = 0; while( token_end < str.size() && token_end != std::string::npos ) @@ -542,4 +587,4 @@ wxString ALTIUM_PARSER::ReadUnicodeString( const std::map& a } return ReadString( aProps, aKey, aDefault ); -} +} \ No newline at end of file diff --git a/common/plugins/altium/altium_parser.h b/common/plugins/altium/altium_parser.h index 05520f6014..d1bdb29774 100644 --- a/common/plugins/altium/altium_parser.h +++ b/common/plugins/altium/altium_parser.h @@ -30,9 +30,13 @@ #include #include +#include +#include #include #include +#include +#include namespace CFB { @@ -75,6 +79,8 @@ public: const std::string aName, const bool aIsStream ) const; + std::map GetLibSymbols( const CFB::COMPOUND_FILE_ENTRY* aStart ) const; + private: std::unique_ptr m_reader; std::vector m_buffer; @@ -238,7 +244,12 @@ public: return length; } - std::map ReadProperties(); + std::map ReadProperties( + std::function( const std::string& )> handleBinaryData = + []( const std::string& ) + { + return std::map(); + } ); static int32_t ConvertToKicadUnit( const double aValue ); @@ -311,4 +322,110 @@ private: }; +class ALTIUM_BINARY_READER +{ +public: + ALTIUM_BINARY_READER( const std::string& binaryData ) : m_data( binaryData ), m_position( 0 ) {} + + int32_t ReadInt32() + { + if( m_position + sizeof( int32_t ) > m_data.size() ) + throw std::out_of_range( "ALTIUM_BINARY_READER: out of range" ); + + int32_t value = *reinterpret_cast( &m_data[m_position] ); + m_position += sizeof( int32_t ); + return value; + } + + int16_t ReadInt16() + { + if( m_position + sizeof( int16_t ) > m_data.size() ) + throw std::out_of_range( "ALTIUM_BINARY_READER: out of range" ); + + int16_t value = *reinterpret_cast( &m_data[m_position] ); + m_position += sizeof( int16_t ); + return value; + } + + uint8_t ReadByte() + { + if( m_position + sizeof( uint8_t ) > m_data.size() ) + throw std::out_of_range( "ALTIUM_BINARY_READER: out of range" ); + + uint8_t value = *reinterpret_cast( &m_data[m_position] ); + m_position += sizeof( uint8_t ); + return value; + } + + std::string ReadPascalString() + { + uint8_t length = ReadByte(); + + if( m_position + length > m_data.size() ) + throw std::out_of_range( "ALTIUM_BINARY_READER: out of range" ); + + std::string pascalString( &m_data[m_position], &m_data[m_position + length] ); + m_position += length; + return pascalString; + } + +private: + const std::string& m_data; + size_t m_position; +}; + +class ALTIUM_COMPRESSED_READER : public ALTIUM_BINARY_READER +{ +public: + ALTIUM_COMPRESSED_READER( const std::string& aData ) : ALTIUM_BINARY_READER( aData ) + {} + + std::pair ReadCompressedString() + { + std::string result; + int id = -1; + + while( true ) + { + uint8_t byte = ReadByte(); + if( byte != 0xD0 ) + throw std::runtime_error( "ALTIUM_COMPRESSED_READER: invalid compressed string" ); + + std::string str = ReadPascalString(); + + id = std::stoi( str ); + + std::string data = ReadPascalString(); + + result = decompressData( data ); + } + + return std::make_pair( id, result ); + } + +private: + std::string decompressData( std::string& aData ) + { + // Create a memory input stream with the buffer + wxMemoryInputStream memStream( (void*) aData.data(), aData.length() ); + + // Create a zlib input stream with the memory input stream + wxZlibInputStream zStream( memStream ); + + // Prepare a string to hold decompressed data + std::string decompressedData; + + // Read decompressed data from the zlib input stream + while( !zStream.Eof() ) + { + char buffer[1024]; + zStream.Read( buffer, sizeof( buffer ) ); + size_t bytesRead = zStream.LastRead(); + decompressedData.append( buffer, bytesRead ); + } + + return decompressedData; + } +}; + #endif //ALTIUM_PARSER_H diff --git a/eeschema/dialogs/panel_sym_lib_table.cpp b/eeschema/dialogs/panel_sym_lib_table.cpp index 238332490e..52ff2c3430 100644 --- a/eeschema/dialogs/panel_sym_lib_table.cpp +++ b/eeschema/dialogs/panel_sym_lib_table.cpp @@ -310,7 +310,7 @@ PANEL_SYM_LIB_TABLE::PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, P fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" ) + fileFiltersStr; - + attr->SetEditor( new GRID_CELL_PATH_EDITOR( m_parent, aGrid, &cfg->m_lastSymbolLibDir, fileFiltersStr, true, m_project->GetProjectPath() ) ); @@ -831,7 +831,7 @@ void PANEL_SYM_LIB_TABLE::onConvertLegacyLibraries( wxCommandEvent& event ) for( int row : selectedRows ) { - if( m_cur_grid->GetCellValue( row, COL_TYPE ) != databaseType && + if( m_cur_grid->GetCellValue( row, COL_TYPE ) != databaseType && m_cur_grid->GetCellValue( row, COL_TYPE ) != kicadType ) { legacyRows.push_back( row ); diff --git a/eeschema/sch_plugins/altium/altium_lib_plugin_cache.h b/eeschema/sch_plugins/altium/altium_lib_plugin_cache.h new file mode 100644 index 0000000000..162d034651 --- /dev/null +++ b/eeschema/sch_plugins/altium/altium_lib_plugin_cache.h @@ -0,0 +1,45 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef _ALTIUM_LIB_PLUGIN_CACHE_ +#define _ALTIUM_LIB_PLUGIN_CACHE_ + +#include "../sch_lib_plugin_cache.h" + +class FILE_LINE_READER; +class SCH_SEXPR_PLUGIN; + +/** + * A cache assistant for Altium symbol libraries. + */ +class ALTIUM_LIB_PLUGIN_CACHE : public SCH_LIB_PLUGIN_CACHE +{ +public: + ALTIUM_LIB_PLUGIN_CACHE( const wxString& aLibraryPath ); + virtual ~ALTIUM_LIB_PLUGIN_CACHE(); + + void Load() override; + +private: + friend SCH_SEXPR_PLUGIN; + +}; + +#endif // _ALTIUM_LIB_PLUGIN_CACHE_ diff --git a/eeschema/sch_plugins/altium/altium_parser_sch.cpp b/eeschema/sch_plugins/altium/altium_parser_sch.cpp index 8824753be3..b4b537b4f2 100644 --- a/eeschema/sch_plugins/altium/altium_parser_sch.cpp +++ b/eeschema/sch_plugins/altium/altium_parser_sch.cpp @@ -145,6 +145,8 @@ ASCH_PIN::ASCH_PIN( const std::map& aProps ) { wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::PIN ); + isKiCadLibPin = ALTIUM_PARSER::ReadBool( aProps, "ISKICADLIBPIN", false ); + ownerindex = ReadOwnerIndex( aProps ); ownerpartid = ReadOwnerPartId( aProps ); ownerpartdisplaymode = ALTIUM_PARSER::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 ); @@ -154,29 +156,27 @@ ASCH_PIN::ASCH_PIN( const std::map& aProps ) designator = ALTIUM_PARSER::ReadString( aProps, "DESIGNATOR", "" ); int symbolOuterInt = ALTIUM_PARSER::ReadInt( aProps, "SYMBOL_OUTER", 0 ); - symbolOuter = static_cast( symbolOuterInt ); + symbolOuter = ASCH_PIN_SYMBOL::FromInt( symbolOuterInt ); int symbolInnerInt = ALTIUM_PARSER::ReadInt( aProps, "SYMBOL_INNER", 0 ); - symbolInner = static_cast( symbolInnerInt ); + symbolInner = ASCH_PIN_SYMBOL::FromInt( symbolInnerInt ); int symbolOuterEdgeInt = ALTIUM_PARSER::ReadInt( aProps, "SYMBOL_OUTEREDGE", 0 ); - symbolOuterEdge = ( symbolOuterEdgeInt == 0 || symbolOuterEdgeInt == 1 - || symbolOuterEdgeInt == 4 || symbolOuterEdgeInt == 17 ) ? - static_cast( symbolOuterEdgeInt ) : - ASCH_PIN_SYMBOL_OUTEREDGE::NO_SYMBOL; + symbolOuterEdge = ASCH_PIN_SYMBOL::FromInt( symbolOuterEdgeInt ); int symbolInnerEdgeInt = ALTIUM_PARSER::ReadInt( aProps, "SYMBOL_INNEREDGE", 0 ); - symbolInnerEdge = ( symbolInnerEdgeInt == 0 || symbolInnerEdgeInt == 3 ) ? - static_cast( symbolInnerEdgeInt ) : - ASCH_PIN_SYMBOL_INNEREDGE::NO_SYMBOL; + symbolInnerEdge = ASCH_PIN_SYMBOL::FromInt( symbolInnerEdgeInt ); + electrical = ReadEnum( aProps, "ELECTRICAL", 0, 7, ASCH_PIN_ELECTRICAL::INPUT ); int pinconglomerate = ALTIUM_PARSER::ReadInt( aProps, "PINCONGLOMERATE", 0 ); orientation = static_cast( pinconglomerate & 0x03 ); + hidden = ( pinconglomerate & 0x04 ) != 0; showPinName = ( pinconglomerate & 0x08 ) != 0; showDesignator = ( pinconglomerate & 0x10 ) != 0; + // graphically locked pins are in bit 0x40, but we don't care about that int x = ALTIUM_PARSER::ReadInt( aProps, "LOCATION.X", 0 ); int xfrac = ALTIUM_PARSER::ReadInt( aProps, "LOCATION.X_FRAC", 0 ); @@ -194,26 +194,35 @@ ASCH_PIN::ASCH_PIN( const std::map& aProps ) int kicadY = y; int kicadYfrac = yfrac; + int offsetY = p; + int offsetYfrac = pfrac; + + if( isKiCadLibPin ) + { + offsetY = -offsetY; + offsetYfrac = -offsetYfrac; + } + switch( orientation ) { case ASCH_RECORD_ORIENTATION::RIGHTWARDS: - kicadX += p; - kicadXfrac += pfrac; + kicadX += offsetY; + kicadXfrac += offsetYfrac; break; case ASCH_RECORD_ORIENTATION::UPWARDS: - kicadY += p; - kicadYfrac += pfrac; + kicadY += offsetY; + kicadYfrac += offsetYfrac; break; case ASCH_RECORD_ORIENTATION::LEFTWARDS: - kicadX -= p; - kicadXfrac -= pfrac; + kicadX -= offsetY; + kicadXfrac -= offsetYfrac; break; case ASCH_RECORD_ORIENTATION::DOWNWARDS: - kicadY -= p; - kicadYfrac -= pfrac; + kicadY -= offsetY; + kicadYfrac -= offsetYfrac; break; default: @@ -226,6 +235,35 @@ ASCH_PIN::ASCH_PIN( const std::map& aProps ) } +ASCH_FILL_INTERFACE::ASCH_FILL_INTERFACE( const std::map& aProps ) +{ + AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 ); + IsSolid = ALTIUM_PARSER::ReadBool( aProps, "ISSOLID", false ); + IsTransparent = ALTIUM_PARSER::ReadBool( aProps, "TRANSPARENT", false ); +} + + +ASCH_BORDER_INTERFACE::ASCH_BORDER_INTERFACE( const std::map& aProps ) +{ + LineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" ); + + // Altium line width 0 means hairline. Since KiCad doesn't have a hairline, we + // represent it as a 1 mil line. + if( LineWidth == 0 ) + LineWidth = 1; + + Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 ); +} + +ASCH_SHAPE_INTERFACE::ASCH_SHAPE_INTERFACE( const std::map& aProps ) +{ + OwnerIndex = ReadOwnerIndex( aProps ); + OwnerPartID = ReadOwnerPartId( aProps ); + IndexInSheet = ALTIUM_PARSER::ReadInt( aProps, "INDEXINSHEET", 0 ); + OwnerPartDisplayMode = ALTIUM_PARSER::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 ); +} + + ASCH_LABEL::ASCH_LABEL( const std::map& aProps ) { wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::LABEL ); @@ -271,10 +309,15 @@ ASCH_TEXT_FRAME::ASCH_TEXT_FRAME( const std::map& aProps ) IsWordWrapped = ALTIUM_PARSER::ReadBool( aProps, "WORDWRAP", false ); ShowBorder = ALTIUM_PARSER::ReadBool( aProps, "SHOWBORDER", false ); TextMargin = ReadKiCadUnitFrac( aProps, "TEXTMARGIN" ); + AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 ); BorderColor = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 ); + TextColor = ALTIUM_PARSER::ReadInt( aProps, "TEXTCOLOR", 0 ); + + BorderWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" ); + isSolid = ALTIUM_PARSER::ReadBool( aProps, "ISSOLID", false ); - IsSolid = ALTIUM_PARSER::ReadBool( aProps, "WORDWRAP", true ); + IsWordWrapped = ALTIUM_PARSER::ReadBool( aProps, "WORDWRAP", true ); Alignment = ReadEnum( aProps, "ALIGNMENT", 1, 3, ASCH_TEXT_FRAME_ALIGNMENT::LEFT ); @@ -290,14 +333,12 @@ ASCH_NOTE::ASCH_NOTE( const std::map& aProperties ) : } -ASCH_BEZIER::ASCH_BEZIER( const std::map& aProps ) +ASCH_BEZIER::ASCH_BEZIER( const std::map& aProps ) : + ASCH_SHAPE_INTERFACE( aProps ), + ASCH_BORDER_INTERFACE( aProps ) { wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::BEZIER ); - ownerindex = ReadOwnerIndex( aProps ); - ownerpartid = ReadOwnerPartId( aProps ); - ownerpartdisplaymode = ALTIUM_PARSER::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 ); - int locationCount = ALTIUM_PARSER::ReadInt( aProps, "LOCATIONCOUNT", 0 ); for( int i = 1; i <= locationCount; i++ ) @@ -306,19 +347,15 @@ ASCH_BEZIER::ASCH_BEZIER( const std::map& aProps ) points.emplace_back( ReadKiCadUnitFrac( aProps, "X" + si ), -ReadKiCadUnitFrac( aProps, "Y" + si ) ); } - - lineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" ); } -ASCH_POLYLINE::ASCH_POLYLINE( const std::map& aProps ) +ASCH_POLYLINE::ASCH_POLYLINE( const std::map& aProps ) : + ASCH_SHAPE_INTERFACE( aProps ), + ASCH_BORDER_INTERFACE( aProps ) { wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::POLYLINE ); - OwnerIndex = ReadOwnerIndex( aProps ); - OwnerPartID = ReadOwnerPartId( aProps ); - OwnerPartDisplayMode = ALTIUM_PARSER::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 ); - int locationCount = ALTIUM_PARSER::ReadInt( aProps, "LOCATIONCOUNT", 0 ); for( int i = 1; i <= locationCount; i++ ) @@ -328,9 +365,6 @@ ASCH_POLYLINE::ASCH_POLYLINE( const std::map& aProps ) -ReadKiCadUnitFrac( aProps, "Y" + si ) ); } - LineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" ); - Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 ); - int linestyleVar = ALTIUM_PARSER::ReadInt( aProps, "LINESTYLEEXT", 0 ); // overwrite if present. @@ -341,14 +375,13 @@ ASCH_POLYLINE::ASCH_POLYLINE( const std::map& aProps ) } -ASCH_POLYGON::ASCH_POLYGON( const std::map& aProps ) +ASCH_POLYGON::ASCH_POLYGON( const std::map& aProps ) : + ASCH_SHAPE_INTERFACE( aProps ), + ASCH_FILL_INTERFACE( aProps ), + ASCH_BORDER_INTERFACE( aProps ) { wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::POLYGON ); - OwnerIndex = ReadOwnerIndex( aProps ); - OwnerPartID = ReadOwnerPartId( aProps ); - OwnerPartDisplayMode = ALTIUM_PARSER::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 ); - int locationCount = ALTIUM_PARSER::ReadInt( aProps, "LOCATIONCOUNT", 0 ); for( int i = 1; i <= locationCount; i++ ) @@ -357,23 +390,16 @@ ASCH_POLYGON::ASCH_POLYGON( const std::map& aProps ) points.emplace_back( ReadKiCadUnitFrac( aProps, "X" + si ), -ReadKiCadUnitFrac( aProps, "Y" + si ) ); } - - LineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" ); - IsSolid = ALTIUM_PARSER::ReadBool( aProps, "ISSOLID", false ); - - Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 ); - AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 ); } -ASCH_ROUND_RECTANGLE::ASCH_ROUND_RECTANGLE( const std::map& aProps ) +ASCH_ROUND_RECTANGLE::ASCH_ROUND_RECTANGLE( const std::map& aProps ) : + ASCH_SHAPE_INTERFACE( aProps ), + ASCH_FILL_INTERFACE( aProps ), + ASCH_BORDER_INTERFACE( aProps ) { wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::ROUND_RECTANGLE ); - OwnerIndex = ReadOwnerIndex( aProps ); - OwnerPartID = ReadOwnerPartId( aProps ); - OwnerPartDisplayMode = ALTIUM_PARSER::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 ); - BottomLeft = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ), -ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) ); TopRight = VECTOR2I( ReadKiCadUnitFrac( aProps, "CORNER.X" ), @@ -381,25 +407,16 @@ ASCH_ROUND_RECTANGLE::ASCH_ROUND_RECTANGLE( const std::map& CornerRadius = wxSize( ReadKiCadUnitFrac( aProps, "CORNERXRADIUS" ), -ReadKiCadUnitFrac( aProps, "CORNERYRADIUS" ) ); - - LineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" ); - IsSolid = ALTIUM_PARSER::ReadBool( aProps, "ISSOLID", false ); - IsTransparent = ALTIUM_PARSER::ReadBool( aProps, "TRANSPARENT", false ); - - Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 ); - AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 ); } -ASCH_ARC::ASCH_ARC( const std::map& aProps ) +ASCH_ARC::ASCH_ARC( const std::map& aProps ) : + ASCH_SHAPE_INTERFACE( aProps ), + ASCH_BORDER_INTERFACE( aProps ) { m_IsElliptical = ReadRecord( aProps ) == ALTIUM_SCH_RECORD::ELLIPTICAL_ARC; wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::ARC || m_IsElliptical ); - ownerindex = ReadOwnerIndex( aProps ); - ownerpartid = ReadOwnerPartId( aProps ); - ownerpartdisplaymode = ALTIUM_PARSER::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 ); - m_Center = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ), -ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) ); m_Radius = ReadKiCadUnitFrac( aProps, "RADIUS" ); @@ -410,44 +427,36 @@ ASCH_ARC::ASCH_ARC( const std::map& aProps ) m_StartAngle = ALTIUM_PARSER::ReadDouble( aProps, "STARTANGLE", 0 ); m_EndAngle = ALTIUM_PARSER::ReadDouble( aProps, "ENDANGLE", 0 ); - - m_LineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" ); } -ASCH_ELLIPSE::ASCH_ELLIPSE( const std::map& aProps ) +ASCH_ELLIPSE::ASCH_ELLIPSE( const std::map& aProps ) : + ASCH_SHAPE_INTERFACE( aProps ), + ASCH_FILL_INTERFACE( aProps ), + ASCH_BORDER_INTERFACE( aProps ) { wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::ELLIPSE ); - OwnerIndex = ReadOwnerIndex( aProps ); - OwnerPartID = ReadOwnerPartId( aProps ); - Center = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ), -ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) ); Radius = ReadKiCadUnitFrac( aProps, "RADIUS" ); SecondaryRadius = ReadKiCadUnitFrac( aProps, "SECONDARYRADIUS" ); - AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 ); IsNotAccesible = ALTIUM_PARSER::ReadBool( aProps, "ISNOTACCESIBLE", false ); - IsSolid = ALTIUM_PARSER::ReadBool( aProps, "ISSOLID", false ); } -ASCH_LINE::ASCH_LINE( const std::map& aProps ) +ASCH_LINE::ASCH_LINE( const std::map& aProps ) : + ASCH_SHAPE_INTERFACE( aProps ), + ASCH_BORDER_INTERFACE( aProps ) { wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::LINE ); - ownerindex = ReadOwnerIndex( aProps ); - ownerpartid = ReadOwnerPartId( aProps ); - ownerpartdisplaymode = ALTIUM_PARSER::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 ); - point1 = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ), -ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) ); point2 = VECTOR2I( ReadKiCadUnitFrac( aProps, "CORNER.X" ), -ReadKiCadUnitFrac( aProps, "CORNER.Y" ) ); - - lineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" ); } @@ -541,25 +550,18 @@ ASCH_HARNESS_TYPE::ASCH_HARNESS_TYPE( const std::map& aProps } -ASCH_RECTANGLE::ASCH_RECTANGLE( const std::map& aProps ) +ASCH_RECTANGLE::ASCH_RECTANGLE( const std::map& aProps ) : + ASCH_SHAPE_INTERFACE( aProps ), + ASCH_FILL_INTERFACE( aProps ), + ASCH_BORDER_INTERFACE( aProps ) { wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::RECTANGLE ); - OwnerIndex = ReadOwnerIndex( aProps ); - OwnerPartID = ReadOwnerPartId( aProps ); - OwnerPartDisplayMode = ALTIUM_PARSER::ReadInt( aProps, "OWNERPARTDISPLAYMODE", 0 ); - BottomLeft = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ), -ReadKiCadUnitFrac( aProps, "LOCATION.Y" ) ); TopRight = VECTOR2I( ReadKiCadUnitFrac( aProps, "CORNER.X" ), -ReadKiCadUnitFrac( aProps, "CORNER.Y" ) ); - LineWidth = ReadKiCadUnitFrac( aProps, "LINEWIDTH" ); - IsSolid = ALTIUM_PARSER::ReadBool( aProps, "ISSOLID", false ); - IsTransparent = ALTIUM_PARSER::ReadBool( aProps, "TRANSPARENT", false ); - - Color = ALTIUM_PARSER::ReadInt( aProps, "COLOR", 0 ); - AreaColor = ALTIUM_PARSER::ReadInt( aProps, "AREACOLOR", 0 ); } @@ -724,14 +726,12 @@ ASCH_JUNCTION::ASCH_JUNCTION( const std::map& aProps ) } -ASCH_IMAGE::ASCH_IMAGE( const std::map& aProps ) +ASCH_IMAGE::ASCH_IMAGE( const std::map& aProps ) : + ASCH_SHAPE_INTERFACE( aProps ), + ASCH_BORDER_INTERFACE( aProps ) { wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::IMAGE ); - indexinsheet = ALTIUM_PARSER::ReadInt( aProps, "INDEXINSHEET", 0 ); - ownerindex = ReadOwnerIndex( aProps ); - ownerpartid = ReadOwnerPartId( aProps ); - filename = ALTIUM_PARSER::ReadString( aProps, "FILENAME", "" ); location = VECTOR2I( ReadKiCadUnitFrac( aProps, "LOCATION.X" ), @@ -919,3 +919,12 @@ ASCH_PARAMETER::ASCH_PARAMETER( const std::map& aProps ) isMirrored = ALTIUM_PARSER::ReadBool( aProps, "ISMIRRORED", false ); isShowName = ALTIUM_PARSER::ReadBool( aProps, "SHOWNAME", false ); } + + +ASCH_HYPERLINK::ASCH_HYPERLINK( const std::map& aProps ) : + ASCH_LABEL( aProps ) +{ + wxASSERT( ReadRecord( aProps ) == ALTIUM_SCH_RECORD::HYPERLINK ); + + url = ALTIUM_PARSER::ReadString( aProps, "URL", "" ); +} \ No newline at end of file diff --git a/eeschema/sch_plugins/altium/altium_parser_sch.h b/eeschema/sch_plugins/altium/altium_parser_sch.h index 8a20544192..761aac01e5 100644 --- a/eeschema/sch_plugins/altium/altium_parser_sch.h +++ b/eeschema/sch_plugins/altium/altium_parser_sch.h @@ -104,7 +104,7 @@ enum class ALTIUM_SCH_RECORD HARNESS_TYPE = 217, SIGNAL_HARNESS = 218, BLANKET = 225, - RECORD_226 = 226, + HYPERLINK = 226, }; @@ -122,12 +122,26 @@ struct ASCH_SHAPE_INTERFACE int OwnerIndex; int OwnerPartID; int OwnerPartDisplayMode; + int IndexInSheet; + + explicit ASCH_SHAPE_INTERFACE( const std::map& aProps ); +}; - int LineWidth; +struct ASCH_FILL_INTERFACE +{ + int AreaColor; bool IsSolid; + bool IsTransparent; + + explicit ASCH_FILL_INTERFACE( const std::map& aProps ); +}; +struct ASCH_BORDER_INTERFACE +{ + int LineWidth; int Color; - int AreaColor; + + explicit ASCH_BORDER_INTERFACE( const std::map& aProps ); }; @@ -151,52 +165,125 @@ struct ASCH_SYMBOL }; -enum class ASCH_PIN_SYMBOL_OUTER +enum class ASCH_PIN_SYMBOL_EDGE { UNKNOWN = -1, NO_SYMBOL = 0, - RIGHT_LEFT_SIGNAL_FLOW = 2, - ANALOG_SIGNAL_IN = 5, - NOT_LOGIC_CONNECTION = 6, - DIGITAL_SIGNAL_IN = 25, - LEFT_RIGHT_SIGNAL_FLOW = 33, - BIDI_SIGNAL_FLOW = 34 -}; - - -enum class ASCH_PIN_SYMBOL_INNER -{ - UNKNOWN = -1, - NO_SYMBOL = 0, - POSPONED_OUTPUT = 8, + NEGATED = 1, + RIGHTLEFT = 2, + CLOCK = 3, + LOW_INPUT = 4, + ANALOG_IN = 5, + NOLOGICCONNECT = 6, + // 7 is missing + POSTPONE_OUTPUT = 8, OPEN_COLLECTOR = 9, HIZ = 10, HIGH_CURRENT = 11, PULSE = 12, SCHMITT = 13, + // 14-16 missing + LOW_OUTPUT = 17, + // 18-21 missing OPEN_COLLECTOR_PULL_UP = 22, OPEN_EMITTER = 23, OPEN_EMITTER_PULL_UP = 24, + DIGITAL_IN = 25, + // 26-29 missing SHIFT_LEFT = 30, - OPEN_OUTPUT = 32 -}; - - -enum class ASCH_PIN_SYMBOL_OUTEREDGE -{ - UNKNOWN = -1, - NO_SYMBOL = 0, - NEGATED = 1, - LOW_INPUT = 4, - LOW_OUTPUT = 17 -}; - - -enum class ASCH_PIN_SYMBOL_INNEREDGE -{ - UNKNOWN = -1, - NO_SYMBOL = 0, - CLOCK = 3, + // 31 is missing + OPEN_OUTPUT = 32, + LEFTRIGHT = 33, + BIDI = 34 +}; + +class ASCH_PIN_SYMBOL +{ +public: + enum PTYPE + { + UNKNOWN = -1, + NO_SYMBOL = 0, + NEGATED = 1, + RIGHTLEFT = 2, + CLOCK = 3, + LOW_INPUT = 4, + ANALOG_IN = 5, + NOLOGICCONNECT = 6, + // 7 is missing + POSTPONE_OUTPUT = 8, + OPEN_COLLECTOR = 9, + HIZ = 10, + HIGH_CURRENT = 11, + PULSE = 12, + SCHMITT = 13, + // 14-16 missing + LOW_OUTPUT = 17, + // 18-21 missing + OPEN_COLLECTOR_PULL_UP = 22, + OPEN_EMITTER = 23, + OPEN_EMITTER_PULL_UP = 24, + DIGITAL_IN = 25, + // 26-29 missing + SHIFT_LEFT = 30, + // 31 is missing + OPEN_OUTPUT = 32, + LEFTRIGHT = 33, + BIDI = 34 + }; + + static PTYPE FromInt( int aInt ) + { + switch( aInt ) + { + case 0: + return NO_SYMBOL; + case 1: + return NEGATED; + case 2: + return RIGHTLEFT; + case 3: + return CLOCK; + case 4: + return LOW_INPUT; + case 5: + return ANALOG_IN; + case 6: + return NOLOGICCONNECT; + case 8: + return POSTPONE_OUTPUT; + case 9: + return OPEN_COLLECTOR; + case 10: + return HIZ; + case 11: + return HIGH_CURRENT; + case 12: + return PULSE; + case 13: + return SCHMITT; + case 17: + return LOW_OUTPUT; + case 22: + return OPEN_COLLECTOR_PULL_UP; + case 23: + return OPEN_EMITTER; + case 24: + return OPEN_EMITTER_PULL_UP; + case 25: + return DIGITAL_IN; + case 30: + return SHIFT_LEFT; + case 32: + return OPEN_OUTPUT; + case 33: + return LEFTRIGHT; + case 34: + return BIDI; + default: + return UNKNOWN; + } + } }; @@ -225,11 +312,11 @@ struct ASCH_PIN wxString text; wxString designator; - ASCH_PIN_SYMBOL_OUTER symbolOuter; - ASCH_PIN_SYMBOL_INNER symbolInner; + ASCH_PIN_SYMBOL::PTYPE symbolOuter; + ASCH_PIN_SYMBOL::PTYPE symbolInner; - ASCH_PIN_SYMBOL_OUTEREDGE symbolOuterEdge; - ASCH_PIN_SYMBOL_INNEREDGE symbolInnerEdge; + ASCH_PIN_SYMBOL::PTYPE symbolOuterEdge; + ASCH_PIN_SYMBOL::PTYPE symbolInnerEdge; ASCH_PIN_ELECTRICAL electrical; ASCH_RECORD_ORIENTATION orientation; @@ -241,6 +328,9 @@ struct ASCH_PIN bool showPinName; bool showDesignator; + bool hidden; + + bool isKiCadLibPin; // Tracking variable to handle LibEdit nuance explicit ASCH_PIN( const std::map& aProps ); }; @@ -278,6 +368,7 @@ struct ASCH_LABEL VECTOR2I location; wxString text; + int textColor; int fontId; bool isMirrored; @@ -288,6 +379,13 @@ struct ASCH_LABEL explicit ASCH_LABEL( const std::map& aProps ); }; +struct ASCH_HYPERLINK : ASCH_LABEL +{ + wxString url; + + explicit ASCH_HYPERLINK( const std::map& aProps ); +}; + struct ASCH_TEXT_FRAME { @@ -302,12 +400,14 @@ struct ASCH_TEXT_FRAME bool IsWordWrapped; // to do when kicad supports this bool ShowBorder; - bool IsSolid; int FontID; int TextMargin; // to do when kicad supports this int AreaColor; + int TextColor; int BorderColor; + int BorderWidth; + bool isSolid; ASCH_TEXT_FRAME_ALIGNMENT Alignment; @@ -323,16 +423,10 @@ struct ASCH_NOTE : ASCH_TEXT_FRAME }; -struct ASCH_BEZIER +struct ASCH_BEZIER : ASCH_SHAPE_INTERFACE, ASCH_BORDER_INTERFACE { - int ownerindex; - int ownerpartid; - int ownerpartdisplaymode; - std::vector points; - int lineWidth; - explicit ASCH_BEZIER( const std::map& aProps ); }; @@ -355,24 +449,17 @@ enum class ASCH_SHEET_ENTRY_SIDE }; -struct ASCH_POLYLINE +struct ASCH_POLYLINE : ASCH_SHAPE_INTERFACE, ASCH_BORDER_INTERFACE { - int OwnerIndex; - int OwnerPartID; - int OwnerPartDisplayMode; - std::vector Points; - int LineWidth; - int Color; - ASCH_POLYLINE_LINESTYLE LineStyle; explicit ASCH_POLYLINE( const std::map& aProps ); }; -struct ASCH_POLYGON : ASCH_SHAPE_INTERFACE +struct ASCH_POLYGON : ASCH_SHAPE_INTERFACE, ASCH_FILL_INTERFACE, ASCH_BORDER_INTERFACE { std::vector points; @@ -380,7 +467,7 @@ struct ASCH_POLYGON : ASCH_SHAPE_INTERFACE }; -struct ASCH_ROUND_RECTANGLE : ASCH_SHAPE_INTERFACE +struct ASCH_ROUND_RECTANGLE : ASCH_SHAPE_INTERFACE, ASCH_FILL_INTERFACE, ASCH_BORDER_INTERFACE { VECTOR2I BottomLeft; VECTOR2I TopRight; @@ -393,12 +480,8 @@ struct ASCH_ROUND_RECTANGLE : ASCH_SHAPE_INTERFACE }; -struct ASCH_ARC +struct ASCH_ARC : ASCH_SHAPE_INTERFACE, ASCH_BORDER_INTERFACE { - int ownerindex; - int ownerpartid; - int ownerpartdisplaymode; - bool m_IsElliptical; VECTOR2I m_Center; int m_Radius; @@ -406,40 +489,27 @@ struct ASCH_ARC double m_StartAngle; double m_EndAngle; - int m_LineWidth; - explicit ASCH_ARC( const std::map& aProps ); }; -struct ASCH_ELLIPSE +struct ASCH_ELLIPSE : ASCH_SHAPE_INTERFACE, ASCH_FILL_INTERFACE, ASCH_BORDER_INTERFACE { - int OwnerIndex; - int OwnerPartID; - VECTOR2I Center; int Radius; double SecondaryRadius; - int AreaColor; - bool IsSolid; bool IsNotAccesible; explicit ASCH_ELLIPSE( const std::map& aProps ); }; -struct ASCH_LINE +struct ASCH_LINE : ASCH_SHAPE_INTERFACE, ASCH_BORDER_INTERFACE { - int ownerindex; - int ownerpartid; - int ownerpartdisplaymode; - VECTOR2I point1; VECTOR2I point2; - int lineWidth; - explicit ASCH_LINE( const std::map& aProps ); }; @@ -526,7 +596,7 @@ struct ASCH_HARNESS_TYPE }; -struct ASCH_RECTANGLE : ASCH_SHAPE_INTERFACE +struct ASCH_RECTANGLE : ASCH_SHAPE_INTERFACE, ASCH_FILL_INTERFACE, ASCH_BORDER_INTERFACE { VECTOR2I BottomLeft; VECTOR2I TopRight; @@ -703,12 +773,8 @@ struct ASCH_JUNCTION }; -struct ASCH_IMAGE +struct ASCH_IMAGE : ASCH_SHAPE_INTERFACE, ASCH_BORDER_INTERFACE { - int indexinsheet; - int ownerindex; - int ownerpartid; - wxString filename; VECTOR2I location; VECTOR2I corner; diff --git a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp index ea3b6d7e7b..ebe2b6eff1 100644 --- a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp +++ b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -79,6 +80,12 @@ static const VECTOR2I GetRelativePosition( const VECTOR2I& aPosition, const SCH_ } +static const VECTOR2I GetLibEditPosition( const VECTOR2I& aPosition ) +{ + return VECTOR2I( aPosition.x, -aPosition.y ); +} + + static COLOR4D GetColorFromInt( int color ) { int red = color & 0x0000FF; @@ -102,10 +109,14 @@ static PLOT_DASH_TYPE GetPlotDashType( const ASCH_POLYLINE_LINESTYLE linestyle ) } -static void SetSchShapeFillAndColor( const ASCH_SHAPE_INTERFACE& elem, SCH_SHAPE* shape ) +static void SetSchShapeLine( const ASCH_BORDER_INTERFACE& elem, SCH_SHAPE* shape ) { shape->SetStroke( STROKE_PARAMS( elem.LineWidth, PLOT_DASH_TYPE::SOLID, GetColorFromInt( elem.Color ) ) ); +} + +static void SetSchShapeFillAndColor( const ASCH_FILL_INTERFACE& elem, SCH_SHAPE* shape ) +{ if( !elem.IsSolid ) { @@ -119,21 +130,83 @@ static void SetSchShapeFillAndColor( const ASCH_SHAPE_INTERFACE& elem, SCH_SHAPE } -static void SetLibShapeFillAndColor( const ASCH_SHAPE_INTERFACE& elem, LIB_SHAPE* shape ) +static void SetLibShapeLine( const ASCH_BORDER_INTERFACE& elem, LIB_SHAPE* shape, ALTIUM_SCH_RECORD aType ) { - shape->SetStroke( STROKE_PARAMS( elem.LineWidth, PLOT_DASH_TYPE::SOLID ) ); + COLOR4D color = GetColorFromInt( elem.Color ); + COLOR4D default_color; + STROKE_PARAMS stroke; - if( !elem.IsSolid ) + switch( aType ) { - shape->SetFillMode( FILL_T::NO_FILL ); + case ALTIUM_SCH_RECORD::ARC: + default_color = COLOR4D( PUREBLUE ); + break; + case ALTIUM_SCH_RECORD::BEZIER: + default_color = COLOR4D( PURERED ); + break; + case ALTIUM_SCH_RECORD::ELLIPSE: + default_color = COLOR4D( PUREBLUE ); + break; + case ALTIUM_SCH_RECORD::ELLIPTICAL_ARC: + default_color = COLOR4D( PUREBLUE ); + break; + case ALTIUM_SCH_RECORD::POLYGON: + default_color = COLOR4D( PUREBLUE ); + break; + case ALTIUM_SCH_RECORD::POLYLINE: + default_color = COLOR4D( BLACK ); + break; + case ALTIUM_SCH_RECORD::RECTANGLE: + default_color = COLOR4D( 0.5, 0, 0, 1.0 ); + break; + case ALTIUM_SCH_RECORD::ROUND_RECTANGLE: + default_color = COLOR4D( PUREBLUE ); + break; + default: + default_color = COLOR4D( PUREBLUE ); + break; } - else if( elem.Color == elem.AreaColor ) + + if( color == default_color ) + color = COLOR4D::UNSPECIFIED; + + shape->SetStroke( STROKE_PARAMS( elem.LineWidth, PLOT_DASH_TYPE::SOLID, color ) ); +} + +static void SetLibShapeFillAndColor( const ASCH_FILL_INTERFACE& elem, LIB_SHAPE* shape, ALTIUM_SCH_RECORD aType, int aStrokeColor ) +{ + COLOR4D bgcolor = GetColorFromInt( elem.AreaColor ); + COLOR4D default_bgcolor; + + switch (aType) { - shape->SetFillMode( FILL_T::FILLED_SHAPE ); + case ALTIUM_SCH_RECORD::RECTANGLE: + default_bgcolor = GetColorFromInt( 11599871 ); // Light Yellow + break; + default: + default_bgcolor = GetColorFromInt( 12632256 ); // Grey + break; } + + if( elem.IsTransparent ) + bgcolor = bgcolor.WithAlpha( 0.5 ); + + if( !elem.IsSolid ) + shape->SetFillMode( FILL_T::NO_FILL ); + else if( elem.AreaColor == aStrokeColor ) + shape->SetFillMode( FILL_T::FILLED_SHAPE ); + else if( bgcolor == default_bgcolor ) + shape->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR ); else + shape->SetFillMode( FILL_T::FILLED_WITH_COLOR ); + + shape->SetFillColor( bgcolor ); + + if( elem.AreaColor == aStrokeColor && shape->GetStroke().GetWidth() == 1 ) { - shape->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR ); + STROKE_PARAMS stroke = shape->GetStroke(); + stroke.SetWidth( -1 ); + shape->SetStroke( stroke ); } } @@ -151,6 +224,13 @@ SCH_ALTIUM_PLUGIN::SCH_ALTIUM_PLUGIN() SCH_ALTIUM_PLUGIN::~SCH_ALTIUM_PLUGIN() { + for( auto& [libName, lib] : m_libCache ) + { + for( auto& [name, symbol] : lib ) + { + delete symbol; + } + } } @@ -702,7 +782,7 @@ void SCH_ALTIUM_PLUGIN::ParseFileHeader( const ALTIUM_COMPOUND_FILE& aAltiumSchF m_reporter->Report( _( "Compile mask not currently supported." ), RPT_SEVERITY_ERROR ); break; - case ALTIUM_SCH_RECORD::RECORD_226: + case ALTIUM_SCH_RECORD::HYPERLINK: break; default: @@ -851,27 +931,37 @@ void SCH_ALTIUM_PLUGIN::ParseComponent( int aIndex, } -void SCH_ALTIUM_PLUGIN::ParsePin( const std::map& aProperties ) + + +void SCH_ALTIUM_PLUGIN::ParsePin( const std::map& aProperties, LIB_SYMBOL* aSymbol ) { ASCH_PIN elem( aProperties ); - const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex ); + LIB_SYMBOL* symbol = aSymbol; + SCH_SYMBOL* schSymbol = nullptr; - if( libSymbolIt == m_libSymbols.end() ) + if( !aSymbol ) { - // TODO: e.g. can depend on Template (RECORD=39 - m_reporter->Report( wxString::Format( wxT( "Pin's owner (%d) not found." ), - elem.ownerindex ), - RPT_SEVERITY_DEBUG ); - return; - } + const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex ); - if( !IsComponentPartVisible( elem.ownerindex, elem.ownerpartdisplaymode ) ) - return; + if( libSymbolIt == m_libSymbols.end() ) + { + // TODO: e.g. can depend on Template (RECORD=39 + m_reporter->Report( wxString::Format( wxT( "Pin's owner (%d) not found." ), + elem.ownerindex ), + RPT_SEVERITY_DEBUG ); + return; + } + + if( !IsComponentPartVisible( elem.ownerindex, elem.ownerpartdisplaymode ) ) + return; - SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); - LIB_PIN* pin = new LIB_PIN( libSymbolIt->second ); - libSymbolIt->second->AddDrawItem( pin ); + schSymbol = m_symbols.at( libSymbolIt->first ); + symbol = libSymbolIt->second; + } + + LIB_PIN* pin = new LIB_PIN( symbol ); + symbol->AddDrawItem( pin, false ); pin->SetUnit( std::max( 0, elem.ownerpartid ) ); @@ -915,10 +1005,10 @@ void SCH_ALTIUM_PLUGIN::ParsePin( const std::map& aPropertie } // TODO: position can be sometimes off a little bit! - pin->SetPosition( GetRelativePosition( pinLocation + m_sheetOffset, symbol ) ); - - // TODO: the following fix is even worse for now? - // pin->SetPosition( GetRelativePosition( elem.kicadLocation, symbol ) ); + if( schSymbol ) + pin->SetPosition( GetRelativePosition( pinLocation + m_sheetOffset, schSymbol ) ); + else + pin->SetPosition( VECTOR2I( pinLocation.x, -pinLocation.y ) ); switch( elem.electrical ) { @@ -961,17 +1051,17 @@ void SCH_ALTIUM_PLUGIN::ParsePin( const std::map& aPropertie break; } - if( elem.symbolOuterEdge == ASCH_PIN_SYMBOL_OUTEREDGE::UNKNOWN ) + if( elem.symbolOuterEdge == ASCH_PIN_SYMBOL::UNKNOWN ) m_reporter->Report( _( "Pin has unexpected outer edge type." ), RPT_SEVERITY_WARNING ); - if( elem.symbolInnerEdge == ASCH_PIN_SYMBOL_INNEREDGE::UNKNOWN ) + if( elem.symbolInnerEdge == ASCH_PIN_SYMBOL::UNKNOWN ) m_reporter->Report( _( "Pin has unexpected inner edge type." ), RPT_SEVERITY_WARNING ); - if( elem.symbolOuterEdge == ASCH_PIN_SYMBOL_OUTEREDGE::NEGATED ) + if( elem.symbolOuterEdge == ASCH_PIN_SYMBOL::NEGATED ) { switch( elem.symbolInnerEdge ) { - case ASCH_PIN_SYMBOL_INNEREDGE::CLOCK: + case ASCH_PIN_SYMBOL::CLOCK: pin->SetShape( GRAPHIC_PINSHAPE::INVERTED_CLOCK ); break; @@ -980,11 +1070,11 @@ void SCH_ALTIUM_PLUGIN::ParsePin( const std::map& aPropertie break; } } - else if( elem.symbolOuterEdge == ASCH_PIN_SYMBOL_OUTEREDGE::LOW_INPUT ) + else if( elem.symbolOuterEdge == ASCH_PIN_SYMBOL::LOW_INPUT ) { switch( elem.symbolInnerEdge ) { - case ASCH_PIN_SYMBOL_INNEREDGE::CLOCK: + case ASCH_PIN_SYMBOL::CLOCK: pin->SetShape( GRAPHIC_PINSHAPE::CLOCK_LOW ); break; @@ -993,7 +1083,7 @@ void SCH_ALTIUM_PLUGIN::ParsePin( const std::map& aPropertie break; } } - else if( elem.symbolOuterEdge == ASCH_PIN_SYMBOL_OUTEREDGE::LOW_OUTPUT ) + else if( elem.symbolOuterEdge == ASCH_PIN_SYMBOL::LOW_OUTPUT ) { pin->SetShape( GRAPHIC_PINSHAPE::OUTPUT_LOW ); } @@ -1001,7 +1091,7 @@ void SCH_ALTIUM_PLUGIN::ParsePin( const std::map& aPropertie { switch( elem.symbolInnerEdge ) { - case ASCH_PIN_SYMBOL_INNEREDGE::CLOCK: + case ASCH_PIN_SYMBOL::CLOCK: pin->SetShape( GRAPHIC_PINSHAPE::CLOCK ); break; @@ -1094,11 +1184,11 @@ void SetTextPositioning( EDA_TEXT* text, ASCH_LABEL_JUSTIFICATION justification, } -void SCH_ALTIUM_PLUGIN::ParseLabel( const std::map& aProperties ) +void SCH_ALTIUM_PLUGIN::ParseLabel( const std::map& aProperties, LIB_SYMBOL* aSymbol ) { ASCH_LABEL elem( aProperties ); - if( elem.ownerpartid == ALTIUM_COMPONENT_NONE ) + if( !aSymbol && elem.ownerpartid == ALTIUM_COMPONENT_NONE ) { std::map variableMap = { { "APPLICATION_BUILDNUMBER", "KICAD_VERSION" }, @@ -1137,24 +1227,36 @@ void SCH_ALTIUM_PLUGIN::ParseLabel( const std::map& aPropert } else { - const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex ); + LIB_SYMBOL* symbol = aSymbol; + SCH_SYMBOL* schsym = nullptr; - if( libSymbolIt == m_libSymbols.end() ) + if( !symbol ) { - // TODO: e.g. can depend on Template (RECORD=39 - m_reporter->Report( wxString::Format( wxT( "Label's owner (%d) not found." ), - elem.ownerindex ), - RPT_SEVERITY_DEBUG ); - return; + const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex ); + + if( libSymbolIt == m_libSymbols.end() ) + { + // TODO: e.g. can depend on Template (RECORD=39 + m_reporter->Report( wxString::Format( wxT( "Label's owner (%d) not found." ), + elem.ownerindex ), + RPT_SEVERITY_DEBUG ); + return; + } + + symbol = libSymbolIt->second; + schsym = m_symbols.at( libSymbolIt->first ); } - SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); - LIB_TEXT* textItem = new LIB_TEXT( libSymbolIt->second ); - libSymbolIt->second->AddDrawItem( textItem ); + LIB_TEXT* textItem = new LIB_TEXT( symbol ); + symbol->AddDrawItem( textItem, false ); - textItem->SetUnit( std::max( 0, elem.ownerpartid ) ); + /// Handle labels that are in a library symbol, not on schematic + if( aSymbol ) + textItem->SetPosition( GetLibEditPosition(elem.location ) ); + else + textItem->SetPosition( GetRelativePosition( elem.location + m_sheetOffset, schsym ) ); - textItem->SetPosition( GetRelativePosition( elem.location + m_sheetOffset, symbol ) ); + textItem->SetUnit( std::max( 0, elem.ownerpartid ) ); textItem->SetText( elem.text ); SetTextPositioning( textItem, elem.justification, elem.orientation ); @@ -1171,10 +1273,14 @@ void SCH_ALTIUM_PLUGIN::ParseLabel( const std::map& aPropert } -void SCH_ALTIUM_PLUGIN::ParseTextFrame( const std::map& aProperties ) +void SCH_ALTIUM_PLUGIN::ParseTextFrame( const std::map& aProperties, LIB_SYMBOL* aSymbol ) { ASCH_TEXT_FRAME elem( aProperties ); - AddTextBox( &elem ); + + if( aSymbol ) + AddLibTextBox( &elem, aSymbol ); + else + AddTextBox( &elem ); } @@ -1188,11 +1294,12 @@ void SCH_ALTIUM_PLUGIN::ParseNote( const std::map& aProperti void SCH_ALTIUM_PLUGIN::AddTextBox(const ASCH_TEXT_FRAME *aElem ) - { +{ SCH_TEXTBOX* textBox = new SCH_TEXTBOX(); VECTOR2I sheetTopRight = aElem->TopRight + m_sheetOffset; - VECTOR2I sheetBottomLeft = aElem->BottomLeft + m_sheetOffset; + VECTOR2I sheetBottomLeft = aElem->BottomLeft +m_sheetOffset; + textBox->SetStart( sheetTopRight ); textBox->SetEnd( sheetBottomLeft ); @@ -1200,7 +1307,7 @@ void SCH_ALTIUM_PLUGIN::AddTextBox(const ASCH_TEXT_FRAME *aElem ) textBox->SetFillColor( GetColorFromInt( aElem->AreaColor ) ); - if( aElem->IsSolid) + if( aElem->isSolid) textBox->SetFillMode( FILL_T::FILLED_WITH_COLOR ); else textBox->SetFilled( false ); @@ -1236,6 +1343,7 @@ void SCH_ALTIUM_PLUGIN::AddTextBox(const ASCH_TEXT_FRAME *aElem ) textBox->SetItalic( font.Italic ); textBox->SetBold( font.Bold ); textBox->SetTextSize( { font.Size / 2, font.Size / 2 } ); + //textBox->SetFont( //how to set font, we have a font mane here: ( font.fontname ); } @@ -1248,7 +1356,52 @@ void SCH_ALTIUM_PLUGIN::AddTextBox(const ASCH_TEXT_FRAME *aElem ) } -void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map& aProperties ) +void SCH_ALTIUM_PLUGIN::AddLibTextBox(const ASCH_TEXT_FRAME *aElem, LIB_SYMBOL *aSymbol ) +{ + LIB_TEXTBOX* textBox = new LIB_TEXTBOX( aSymbol ); + + VECTOR2I sheetTopRight = GetLibEditPosition( aElem->TopRight ); + VECTOR2I sheetBottomLeft = GetLibEditPosition( aElem->BottomLeft ); + + textBox->SetStart( sheetTopRight ); + textBox->SetEnd( sheetBottomLeft ); + + textBox->SetText( aElem->Text ); + + textBox->SetFillColor( GetColorFromInt( aElem->AreaColor ) ); + + if( aElem->isSolid) + textBox->SetFillMode( FILL_T::FILLED_WITH_COLOR ); + else + textBox->SetFilled( false ); + + if( aElem->ShowBorder ) + textBox->SetStroke( STROKE_PARAMS( 0, PLOT_DASH_TYPE::DEFAULT, + GetColorFromInt( aElem->BorderColor ) ) ); + else + textBox->SetStroke( STROKE_PARAMS( -1 ) ); + + switch( aElem->Alignment ) + { + default: + case ASCH_TEXT_FRAME_ALIGNMENT::LEFT: + textBox->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); + break; + case ASCH_TEXT_FRAME_ALIGNMENT::CENTER: + textBox->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER ); + break; + case ASCH_TEXT_FRAME_ALIGNMENT::RIGHT: + textBox->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); + break; + } + + aSymbol->AddDrawItem( textBox, false ); + +} + + +void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map& aProperties, + LIB_SYMBOL* aSymbol ) { ASCH_BEZIER elem( aProperties ); @@ -1261,11 +1414,11 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map& aProper return; } - SCH_SCREEN* screen = getCurrentScreen(); - wxCHECK( screen, /* void */ ); - - if( elem.ownerpartid == ALTIUM_COMPONENT_NONE ) + if( !aSymbol && elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) { + SCH_SCREEN* currentScreen = getCurrentScreen(); + wxCHECK( currentScreen, /* void */ ); + for( size_t i = 0; i + 1 < elem.points.size(); i += 3 ) { if( i + 2 == elem.points.size() ) @@ -1275,11 +1428,11 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map& aProper SCH_LAYER_ID::LAYER_NOTES ); line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset ); - line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); + line->SetStroke( STROKE_PARAMS( elem.LineWidth, PLOT_DASH_TYPE::SOLID ) ); line->SetFlags( IS_NEW ); - screen->Append( line ); + currentScreen->Append( line ); } else { @@ -1299,49 +1452,59 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map& aProper SCH_LAYER_ID::LAYER_NOTES ); line->SetEndPoint( polyPoints.at( k + 1 ) + m_sheetOffset ); - line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); + line->SetStroke( STROKE_PARAMS( elem.LineWidth, PLOT_DASH_TYPE::SOLID ) ); line->SetFlags( IS_NEW ); - screen->Append( line ); + currentScreen->Append( line ); } } } } else { - const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex ); + LIB_SYMBOL* symbol = aSymbol; + SCH_SYMBOL* schsym = nullptr; - if( libSymbolIt == m_libSymbols.end() ) + if( !symbol ) { - // TODO: e.g. can depend on Template (RECORD=39 - m_reporter->Report( wxString::Format( wxT( "Bezier's owner (%d) not found." ), - elem.ownerindex ), - RPT_SEVERITY_DEBUG ); - return; + const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); + + if( libSymbolIt == m_libSymbols.end() ) + { + // TODO: e.g. can depend on Template (RECORD=39 + m_reporter->Report( wxString::Format( wxT( "Bezier's owner (%d) not found." ), + elem.OwnerIndex ), + RPT_SEVERITY_DEBUG ); + return; + } + + symbol = libSymbolIt->second; + schsym = m_symbols.at( libSymbolIt->first ); } - if( !IsComponentPartVisible( elem.ownerindex, elem.ownerpartdisplaymode ) ) + if( !aSymbol && !IsComponentPartVisible( elem.OwnerIndex, elem.OwnerPartDisplayMode ) ) return; - SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); - for( size_t i = 0; i + 1 < elem.points.size(); i += 3 ) { if( i + 2 == elem.points.size() ) { // special case: single line - LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY ); - libSymbolIt->second->AddDrawItem( line ); + LIB_SHAPE* line = new LIB_SHAPE( symbol, SHAPE_T::POLY ); + symbol->AddDrawItem( line, false ); - line->SetUnit( std::max( 0, elem.ownerpartid ) ); + line->SetUnit( std::max( 0, elem.OwnerPartID ) ); for( size_t j = i; j < elem.points.size() && j < i + 2; j++ ) { - line->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset, - symbol ) ); + if( !schsym ) + line->AddPoint( GetLibEditPosition( elem.points.at( j ) ) ); + else + line->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset, + schsym ) ); } - line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); + line->SetStroke( STROKE_PARAMS( elem.LineWidth, PLOT_DASH_TYPE::SOLID ) ); } else if( i + 3 == elem.points.size() ) { @@ -1349,31 +1512,38 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map& aProper // I haven't a clue what this is all about, but the sample document we have in // https://gitlab.com/kicad/code/kicad/-/issues/8974 responds best by treating it // as another single line special case. - LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY ); - libSymbolIt->second->AddDrawItem( line ); + LIB_SHAPE* line = new LIB_SHAPE( symbol, SHAPE_T::POLY ); + symbol->AddDrawItem( line, false ); - line->SetUnit( std::max( 0, elem.ownerpartid ) ); + line->SetUnit( std::max( 0, elem.OwnerPartID ) ); for( size_t j = i; j < elem.points.size() && j < i + 2; j++ ) { - line->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset, - symbol ) ); + if( !schsym ) + line->AddPoint( GetLibEditPosition( elem.points.at( j ) ) ); + else + line->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset, + schsym ) ); } - line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); + line->SetStroke( STROKE_PARAMS( elem.LineWidth, PLOT_DASH_TYPE::SOLID ) ); } else { // Bezier always has exactly 4 control points - LIB_SHAPE* bezier = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::BEZIER ); - libSymbolIt->second->AddDrawItem( bezier ); + LIB_SHAPE* bezier = new LIB_SHAPE( symbol, SHAPE_T::BEZIER ); + symbol->AddDrawItem( bezier, false ); - bezier->SetUnit( std::max( 0, elem.ownerpartid ) ); + bezier->SetUnit( std::max( 0, elem.OwnerPartID ) ); for( size_t j = i; j < elem.points.size() && j < i + 4; j++ ) { - VECTOR2I pos = - GetRelativePosition( elem.points.at( j ) + m_sheetOffset, symbol ); + VECTOR2I pos; + + if( !schsym ) + pos = GetLibEditPosition( elem.points.at( j ) ); + else + pos = GetRelativePosition( elem.points.at( j ) + m_sheetOffset, schsym ); switch( j - i ) { @@ -1385,22 +1555,23 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map& aProper } } - bezier->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); + bezier->SetStroke( STROKE_PARAMS( elem.LineWidth, PLOT_DASH_TYPE::SOLID ) ); } } } } -void SCH_ALTIUM_PLUGIN::ParsePolyline( const std::map& aProperties ) +void SCH_ALTIUM_PLUGIN::ParsePolyline( const std::map& aProperties, + LIB_SYMBOL* aSymbol ) { ASCH_POLYLINE elem( aProperties ); - SCH_SCREEN* screen = getCurrentScreen(); - wxCHECK( screen, /* void */ ); - - if( elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) + if( !aSymbol && elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) { + SCH_SCREEN* screen = getCurrentScreen(); + wxCHECK( screen, /* void */ ); + SCH_SHAPE* poly = new SCH_SHAPE( SHAPE_T::POLY ); for( VECTOR2I& point : elem.Points ) @@ -1414,50 +1585,68 @@ void SCH_ALTIUM_PLUGIN::ParsePolyline( const std::map& aProp } else { - const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); + LIB_SYMBOL* symbol = aSymbol; + SCH_SYMBOL* schsym = nullptr; - if( libSymbolIt == m_libSymbols.end() ) + if( !aSymbol ) { - // TODO: e.g. can depend on Template (RECORD=39 - m_reporter->Report( wxString::Format( wxT( "Polyline's owner (%d) not found." ), - elem.OwnerIndex ), - RPT_SEVERITY_DEBUG ); - return; + const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); + + if( libSymbolIt == m_libSymbols.end() ) + { + // TODO: e.g. can depend on Template (RECORD=39 + m_reporter->Report( wxString::Format( wxT( "Polyline's owner (%d) not found." ), + elem.OwnerIndex ), + RPT_SEVERITY_DEBUG ); + return; + } + + symbol = libSymbolIt->second; + schsym = m_symbols.at( libSymbolIt->first ); } - if( !IsComponentPartVisible( elem.OwnerIndex, elem.OwnerPartDisplayMode ) ) + if( !aSymbol && !IsComponentPartVisible( elem.OwnerIndex, elem.OwnerPartDisplayMode ) ) return; - SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); - LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY ); - libSymbolIt->second->AddDrawItem( line ); + LIB_SHAPE* line = new LIB_SHAPE( symbol, SHAPE_T::POLY ); + symbol->AddDrawItem( line, false ); line->SetUnit( elem.OwnerPartID ); for( VECTOR2I& point : elem.Points ) - line->AddPoint( GetRelativePosition( point + m_sheetOffset, symbol ) ); + { + if( !schsym ) + line->AddPoint( GetLibEditPosition( point ) ); + else + line->AddPoint( GetRelativePosition( point + m_sheetOffset, schsym ) ); + } - line->SetStroke( STROKE_PARAMS( elem.LineWidth, GetPlotDashType( elem.LineStyle ), - GetColorFromInt( elem.Color ) ) ); + SetLibShapeLine( elem, line, ALTIUM_SCH_RECORD::POLYLINE ); + STROKE_PARAMS stroke = line->GetStroke(); + stroke.SetPlotStyle( GetPlotDashType( elem.LineStyle ) ); + + line->SetStroke( stroke ); } } -void SCH_ALTIUM_PLUGIN::ParsePolygon( const std::map& aProperties ) +void SCH_ALTIUM_PLUGIN::ParsePolygon( const std::map& aProperties, + LIB_SYMBOL* aSymbol ) { ASCH_POLYGON elem( aProperties ); - SCH_SCREEN* screen = getCurrentScreen(); - wxCHECK( screen, /* void */ ); - - if( elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) + if( !aSymbol && elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) { + SCH_SCREEN* screen = getCurrentScreen(); + wxCHECK( screen, /* void */ ); + SCH_SHAPE* poly = new SCH_SHAPE( SHAPE_T::POLY ); for( VECTOR2I& point : elem.points ) poly->AddPoint( point + m_sheetOffset ); poly->AddPoint( elem.points.front() + m_sheetOffset ); + SetSchShapeLine( elem, poly ); SetSchShapeFillAndColor( elem, poly ); poly->SetFlags( IS_NEW ); @@ -1465,52 +1654,79 @@ void SCH_ALTIUM_PLUGIN::ParsePolygon( const std::map& aPrope } else { - const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); + LIB_SYMBOL* symbol = aSymbol; + SCH_SYMBOL* schsym = nullptr; - if( libSymbolIt == m_libSymbols.end() ) + if( !aSymbol ) { - // TODO: e.g. can depend on Template (RECORD=39 - m_reporter->Report( wxString::Format( wxT( "Polygon's owner (%d) not found." ), - elem.OwnerIndex ), - RPT_SEVERITY_DEBUG ); - return; + const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); + + if( libSymbolIt == m_libSymbols.end() ) + { + // TODO: e.g. can depend on Template (RECORD=39 + m_reporter->Report( wxString::Format( wxT( "Polygon's owner (%d) not found." ), + elem.OwnerIndex ), + RPT_SEVERITY_DEBUG ); + return; + } + + symbol = libSymbolIt->second; + schsym = m_symbols.at( libSymbolIt->first ); } - if( !IsComponentPartVisible( elem.OwnerIndex, elem.OwnerPartDisplayMode ) ) + if( !aSymbol && !IsComponentPartVisible( elem.OwnerIndex, elem.OwnerPartDisplayMode ) ) return; - SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); - LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY ); - libSymbolIt->second->AddDrawItem( line ); + LIB_SHAPE* line = new LIB_SHAPE( symbol, SHAPE_T::POLY ); + symbol->AddDrawItem( line, false ); line->SetUnit( elem.OwnerPartID ); for( VECTOR2I& point : elem.points ) - line->AddPoint( GetRelativePosition( point + m_sheetOffset, symbol ) ); + { + if( !schsym ) + line->AddPoint( GetLibEditPosition( point ) ); + else + line->AddPoint( GetRelativePosition( point + m_sheetOffset, schsym ) ); + } + + if( !schsym ) + line->AddPoint( GetLibEditPosition( elem.points.front() ) ); + else + line->AddPoint( GetRelativePosition( elem.points.front() + m_sheetOffset, schsym ) ); - line->AddPoint( GetRelativePosition( elem.points.front() + m_sheetOffset, symbol ) ); - SetLibShapeFillAndColor( elem, line ); + SetLibShapeLine( elem, line, ALTIUM_SCH_RECORD::POLYGON ); + SetLibShapeFillAndColor( elem, line, ALTIUM_SCH_RECORD::POLYGON, elem.Color ); + + if( line->GetFillColor() == line->GetStroke().GetColor() && line->GetFillMode() != FILL_T::NO_FILL ) + { + STROKE_PARAMS stroke = line->GetStroke(); + stroke.SetWidth( -1 ); + line->SetStroke( stroke ); + } } } -void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map& aProperties ) +void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map& aProperties, + LIB_SYMBOL* aSymbol ) { ASCH_ROUND_RECTANGLE elem( aProperties ); VECTOR2I sheetTopRight = elem.TopRight + m_sheetOffset; VECTOR2I sheetBottomLeft = elem.BottomLeft + m_sheetOffset; - SCH_SCREEN* screen = getCurrentScreen(); - wxCHECK( screen, /* void */ ); - - if( elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) + if( !aSymbol && elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) { + SCH_SCREEN* screen = getCurrentScreen(); + wxCHECK( screen, /* void */ ); + // TODO: misses rounded edges SCH_SHAPE* rect = new SCH_SHAPE( SHAPE_T::RECTANGLE ); rect->SetPosition( sheetTopRight ); rect->SetEnd( sheetBottomLeft ); + SetSchShapeLine( elem, rect ); SetSchShapeFillAndColor( elem, rect ); rect->SetFlags( IS_NEW ); @@ -1518,36 +1734,67 @@ void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map& } else { - const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); + LIB_SYMBOL* symbol = aSymbol; + SCH_SYMBOL* schsym = nullptr; - if( libSymbolIt == m_libSymbols.end() ) + if( !aSymbol ) { - // TODO: e.g. can depend on Template (RECORD=39 - m_reporter->Report( wxString::Format( wxT( "Rounded rectangle's owner (%d) not " - "found." ), - elem.OwnerIndex ), - RPT_SEVERITY_DEBUG ); - return; + const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); + + if( libSymbolIt == m_libSymbols.end() ) + { + // TODO: e.g. can depend on Template (RECORD=39 + m_reporter->Report( wxString::Format( wxT( "Rounded rectangle's owner (%d) not " + "found." ), + elem.OwnerIndex ), + RPT_SEVERITY_DEBUG ); + return; + } + + symbol = libSymbolIt->second; + schsym = m_symbols.at( libSymbolIt->first ); } - if( !IsComponentPartVisible( elem.OwnerIndex, elem.OwnerPartDisplayMode ) ) + if( !aSymbol && !IsComponentPartVisible( elem.OwnerIndex, elem.OwnerPartDisplayMode ) ) return; - SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); - // TODO: misses rounded edges - LIB_SHAPE* rect = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::RECTANGLE ); - libSymbolIt->second->AddDrawItem( rect ); + LIB_SHAPE* rect = nullptr; - rect->SetUnit( elem.OwnerPartID ); + // If it is a circle, make it a circle + if( elem.CornerRadius.GetX() >= std::abs( elem.TopRight.x - elem.BottomLeft.x ) / 2 + && elem.CornerRadius.GetY() >= std::abs( elem.TopRight.y - elem.BottomLeft.y ) / 2 ) + { + rect = new LIB_SHAPE( symbol, SHAPE_T::CIRCLE ); + rect->SetPosition( GetLibEditPosition( ( sheetTopRight + sheetBottomLeft ) / 2 ) ); + } + else + { + rect = new LIB_SHAPE( symbol, SHAPE_T::RECTANGLE ); + + if( !schsym ) + { + rect->SetPosition( GetLibEditPosition( elem.TopRight ) ); + rect->SetEnd( GetLibEditPosition( elem.BottomLeft ) ); + } + else + { + rect->SetPosition( GetRelativePosition( elem.TopRight + m_sheetOffset, schsym ) ); + rect->SetEnd( GetRelativePosition( elem.BottomLeft + m_sheetOffset, schsym ) ); + } - rect->SetPosition( GetRelativePosition( elem.TopRight + m_sheetOffset, symbol ) ); - rect->SetEnd( GetRelativePosition( elem.BottomLeft + m_sheetOffset, symbol ) ); - SetLibShapeFillAndColor( elem, rect ); + rect->Normalize(); + } + + SetLibShapeLine( elem, rect, ALTIUM_SCH_RECORD::ROUND_RECTANGLE ); + SetLibShapeFillAndColor( elem, rect, ALTIUM_SCH_RECORD::ROUND_RECTANGLE, elem.Color ); + + symbol->AddDrawItem( rect, false ); + rect->SetUnit( elem.OwnerPartID ); } } -void SCH_ALTIUM_PLUGIN::ParseArc( const std::map& aProperties ) +void SCH_ALTIUM_PLUGIN::ParseArc( const std::map& aProperties, LIB_SYMBOL* aSymbol ) { // The Arc can be ALTIUM_SCH_RECORD::ELLIPTICAL_ARC or ALTIUM_SCH_RECORD::ARC // Elliptical arcs are not handled in KiCad. So use an arc instead @@ -1555,9 +1802,6 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map& aPropertie ASCH_ARC elem( aProperties ); - SCH_SCREEN* screen = getCurrentScreen(); - wxCHECK( screen, /* void */ ); - int arc_radius = elem.m_Radius; // Try to approximate this ellipse by an arc. use the biggest of radius and secondary radius @@ -1565,17 +1809,20 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map& aPropertie if( elem.m_IsElliptical ) arc_radius = std::max( elem.m_Radius, elem.m_SecondaryRadius ); - if( elem.ownerpartid == ALTIUM_COMPONENT_NONE ) + if( !aSymbol && elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) { + SCH_SCREEN* currentScreen = getCurrentScreen(); + wxCHECK( currentScreen, /* void */ ); + if( elem.m_StartAngle == 0 && ( elem.m_EndAngle == 0 || elem.m_EndAngle == 360 ) ) { SCH_SHAPE* circle = new SCH_SHAPE( SHAPE_T::CIRCLE ); circle->SetPosition( elem.m_Center + m_sheetOffset ); circle->SetEnd( circle->GetPosition() + VECTOR2I( arc_radius, 0 ) ); - circle->SetStroke( STROKE_PARAMS( elem.m_LineWidth, PLOT_DASH_TYPE::SOLID ) ); + circle->SetStroke( STROKE_PARAMS( elem.LineWidth, PLOT_DASH_TYPE::SOLID ) ); - screen->Append( circle ); + currentScreen->Append( circle ); } else { @@ -1589,47 +1836,61 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map& aPropertie arc->SetStart( elem.m_Center + startOffset + m_sheetOffset ); arc->SetArcAngleAndEnd( includedAngle.Normalize(), true ); - arc->SetStroke( STROKE_PARAMS( elem.m_LineWidth, PLOT_DASH_TYPE::SOLID ) ); + arc->SetStroke( STROKE_PARAMS( elem.LineWidth, PLOT_DASH_TYPE::SOLID ) ); - screen->Append( arc ); + currentScreen->Append( arc ); } } else { - const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex ); + LIB_SYMBOL* symbol = aSymbol; + SCH_SYMBOL* schsym = nullptr; - if( libSymbolIt == m_libSymbols.end() ) + if( !aSymbol ) { - // TODO: e.g. can depend on Template (RECORD=39 - m_reporter->Report( wxString::Format( wxT( "Arc's owner (%d) not found." ), - elem.ownerindex ), - RPT_SEVERITY_DEBUG ); - return; + const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); + + if( libSymbolIt == m_libSymbols.end() ) + { + // TODO: e.g. can depend on Template (RECORD=39 + m_reporter->Report( wxString::Format( wxT( "Arc's owner (%d) not found." ), + elem.OwnerIndex ), + RPT_SEVERITY_DEBUG ); + return; + } + + symbol = libSymbolIt->second; + schsym = m_symbols.at( libSymbolIt->first ); } - if( !IsComponentPartVisible( elem.ownerindex, elem.ownerpartdisplaymode ) ) + if( !aSymbol && !IsComponentPartVisible( elem.OwnerIndex, elem.OwnerPartDisplayMode ) ) return; - SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); - if( elem.m_StartAngle == 0 && ( elem.m_EndAngle == 0 || elem.m_EndAngle == 360 ) ) { - LIB_SHAPE* circle = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::CIRCLE ); - libSymbolIt->second->AddDrawItem( circle ); + LIB_SHAPE* circle = new LIB_SHAPE( symbol, SHAPE_T::CIRCLE ); + symbol->AddDrawItem( circle, false ); - circle->SetUnit( std::max( 0, elem.ownerpartid ) ); + circle->SetUnit( std::max( 0, elem.OwnerPartID ) ); + + if( !schsym ) + circle->SetPosition( GetLibEditPosition( elem.m_Center ) ); + else + circle->SetPosition( GetRelativePosition( elem.m_Center + m_sheetOffset, schsym ) ); - circle->SetPosition( GetRelativePosition( elem.m_Center + m_sheetOffset, symbol ) ); circle->SetEnd( circle->GetPosition() + VECTOR2I( arc_radius, 0 ) ); - circle->SetStroke( STROKE_PARAMS( elem.m_LineWidth, PLOT_DASH_TYPE::SOLID ) ); + SetLibShapeLine( elem, circle, ALTIUM_SCH_RECORD::ARC ); } else { - LIB_SHAPE* arc = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::ARC ); - libSymbolIt->second->AddDrawItem( arc ); - arc->SetUnit( std::max( 0, elem.ownerpartid ) ); + LIB_SHAPE* arc = new LIB_SHAPE( symbol, SHAPE_T::ARC ); + symbol->AddDrawItem( arc, false ); + arc->SetUnit( std::max( 0, elem.OwnerPartID ) ); - arc->SetCenter( GetRelativePosition( elem.m_Center + m_sheetOffset, symbol ) ); + if( !schsym ) + arc->SetCenter( GetLibEditPosition( elem.m_Center ) ); + else + arc->SetCenter( GetRelativePosition( elem.m_Center + m_sheetOffset, schsym ) ); VECTOR2I arcStart( arc_radius, 0 ); RotatePoint( arcStart, -EDA_ANGLE( elem.m_StartAngle, DEGREES_T ) ); @@ -1641,19 +1902,16 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map& aPropertie arcEnd += arc->GetCenter(); arc->SetEnd( arcEnd ); - arc->SetStroke( STROKE_PARAMS( elem.m_LineWidth, PLOT_DASH_TYPE::SOLID ) ); + SetLibShapeLine( elem, arc, ALTIUM_SCH_RECORD::ARC ); } } } -void SCH_ALTIUM_PLUGIN::ParseEllipse( const std::map& aProperties ) +void SCH_ALTIUM_PLUGIN::ParseEllipse( const std::map& aProperties, LIB_SYMBOL* aSymbol ) { ASCH_ELLIPSE elem( aProperties ); - SCH_SCREEN* screen = getCurrentScreen(); - wxCHECK( screen, /* void */ ); - // To do: Import true ellipses when KiCad supports them if( elem.Radius != elem.SecondaryRadius ) { @@ -1665,8 +1923,11 @@ void SCH_ALTIUM_PLUGIN::ParseEllipse( const std::map& aPrope return; } - if( elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) + if( !aSymbol && elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) { + SCH_SCREEN* screen = getCurrentScreen(); + wxCHECK( screen, /* void */ ); + SCH_SHAPE* circle = new SCH_SHAPE( SHAPE_T::CIRCLE ); circle->SetPosition( elem.Center + m_sheetOffset ); @@ -1684,81 +1945,104 @@ void SCH_ALTIUM_PLUGIN::ParseEllipse( const std::map& aPrope } else { - const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); + LIB_SYMBOL* symbol = aSymbol; + SCH_SYMBOL* schsym = nullptr; - if( libSymbolIt == m_libSymbols.end() ) + if( !aSymbol ) { - // TODO: e.g. can depend on Template (RECORD=39 - m_reporter->Report( wxString::Format( wxT( "Ellipse's owner (%d) not found." ), - elem.OwnerIndex ), - RPT_SEVERITY_DEBUG ); - return; - } + const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); - SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); + if( libSymbolIt == m_libSymbols.end() ) + { + // TODO: e.g. can depend on Template (RECORD=39 + m_reporter->Report( wxString::Format( wxT( "Ellipse's owner (%d) not found." ), + elem.OwnerIndex ), + RPT_SEVERITY_DEBUG ); + return; + } - LIB_SHAPE* circle = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::CIRCLE ); - libSymbolIt->second->AddDrawItem( circle ); + symbol = libSymbolIt->second; + schsym = m_symbols.at( libSymbolIt->first ); + } + + LIB_SHAPE* circle = new LIB_SHAPE( symbol, SHAPE_T::CIRCLE ); + symbol->AddDrawItem( circle, false ); circle->SetUnit( elem.OwnerPartID ); - circle->SetPosition( GetRelativePosition( elem.Center + m_sheetOffset, symbol ) ); - circle->SetEnd( circle->GetPosition() + VECTOR2I( elem.Radius, 0 ) ); - circle->SetStroke( STROKE_PARAMS( 1, PLOT_DASH_TYPE::SOLID ) ); + if( !schsym ) + circle->SetPosition( GetLibEditPosition( elem.Center ) ); + else + circle->SetPosition( GetRelativePosition( elem.Center + m_sheetOffset, schsym ) ); - circle->SetFillColor( GetColorFromInt( elem.AreaColor ) ); + circle->SetEnd( circle->GetPosition() + VECTOR2I( elem.Radius, 0 ) ); - if( elem.IsSolid ) - circle->SetFillMode( FILL_T::FILLED_WITH_COLOR ); - else - circle->SetFilled( false ); + SetLibShapeLine( elem, circle, ALTIUM_SCH_RECORD::ELLIPSE ); + SetLibShapeFillAndColor( elem, circle, ALTIUM_SCH_RECORD::ELLIPSE, elem.Color ); } } -void SCH_ALTIUM_PLUGIN::ParseLine( const std::map& aProperties ) +void SCH_ALTIUM_PLUGIN::ParseLine( const std::map& aProperties, LIB_SYMBOL* aSymbol ) { ASCH_LINE elem( aProperties ); - SCH_SCREEN* screen = getCurrentScreen(); - wxCHECK( screen, /* void */ ); - - if( elem.ownerpartid == ALTIUM_COMPONENT_NONE ) + if( !aSymbol && elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) { + + SCH_SCREEN* screen = getCurrentScreen(); + wxCHECK( screen, /* void */ ); + // close polygon SCH_LINE* line = new SCH_LINE( elem.point1 + m_sheetOffset, SCH_LAYER_ID::LAYER_NOTES ); line->SetEndPoint( elem.point2 + m_sheetOffset ); - line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); // TODO? + line->SetStroke( STROKE_PARAMS( elem.LineWidth, PLOT_DASH_TYPE::SOLID ) ); // TODO? line->SetFlags( IS_NEW ); screen->Append( line ); } else { - const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex ); + LIB_SYMBOL* symbol = aSymbol; + SCH_SYMBOL* schsym = nullptr; - if( libSymbolIt == m_libSymbols.end() ) + if( !aSymbol ) { - // TODO: e.g. can depend on Template (RECORD=39 - m_reporter->Report( wxString::Format( wxT( "Line's owner (%d) not found." ), - elem.ownerindex ), - RPT_SEVERITY_DEBUG ); - return; + const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); + + if( libSymbolIt == m_libSymbols.end() ) + { + // TODO: e.g. can depend on Template (RECORD=39 + m_reporter->Report( wxString::Format( wxT( "Line's owner (%d) not found." ), + elem.OwnerIndex ), + RPT_SEVERITY_DEBUG ); + return; + } + + symbol = libSymbolIt->second; + schsym = m_symbols.at( libSymbolIt->first ); } - if( !IsComponentPartVisible( elem.ownerindex, elem.ownerpartdisplaymode ) ) + if( !aSymbol && !IsComponentPartVisible( elem.OwnerIndex, elem.OwnerPartDisplayMode ) ) return; - SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); - LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY ); - libSymbolIt->second->AddDrawItem( line ); + LIB_SHAPE* line = new LIB_SHAPE( symbol, SHAPE_T::POLY ); + symbol->AddDrawItem( line, false ); - line->SetUnit( std::max( 0, elem.ownerpartid ) ); + line->SetUnit( std::max( 0, elem.OwnerPartID ) ); - line->AddPoint( GetRelativePosition( elem.point1 + m_sheetOffset, symbol ) ); - line->AddPoint( GetRelativePosition( elem.point2 + m_sheetOffset, symbol ) ); + if( !schsym ) + { + line->AddPoint( GetLibEditPosition( elem.point1 ) ); + line->AddPoint( GetLibEditPosition( elem.point2 ) ); + } + else + { + line->AddPoint( GetRelativePosition( elem.point1 + m_sheetOffset, schsym ) ); + line->AddPoint( GetRelativePosition( elem.point2 + m_sheetOffset, schsym ) ); + } - line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) ); + line->SetStroke( STROKE_PARAMS( elem.LineWidth, PLOT_DASH_TYPE::SOLID ) ); } } @@ -1767,11 +2051,11 @@ void SCH_ALTIUM_PLUGIN::ParseSignalHarness( const std::map& { ASCH_SIGNAL_HARNESS elem( aProperties ); - SCH_SCREEN* screen = getCurrentScreen(); - wxCHECK( screen, /* void */ ); - if( elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) { + SCH_SCREEN* screen = getCurrentScreen(); + wxCHECK( screen, /* void */ ); + SCH_SHAPE* poly = new SCH_SHAPE( SHAPE_T::POLY ); for( VECTOR2I& point : elem.Points ) @@ -1797,11 +2081,11 @@ void SCH_ALTIUM_PLUGIN::ParseHarnessConnector( int aIndex, const std::map& aP } -void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map& aProperties ) +void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map& aProperties, + LIB_SYMBOL* aSymbol ) { ASCH_RECTANGLE elem( aProperties ); VECTOR2I sheetTopRight = elem.TopRight + m_sheetOffset; VECTOR2I sheetBottomLeft = elem.BottomLeft + m_sheetOffset; - SCH_SCREEN* screen = getCurrentScreen(); - wxCHECK( screen, /* void */ ); - if( elem.OwnerPartID == ALTIUM_COMPONENT_NONE ) { + SCH_SCREEN* screen = getCurrentScreen(); + wxCHECK( screen, /* void */ ); + SCH_SHAPE* rect = new SCH_SHAPE( SHAPE_T::RECTANGLE ); rect->SetPosition( sheetTopRight ); rect->SetEnd( sheetBottomLeft ); + SetSchShapeLine( elem, rect ); SetSchShapeFillAndColor( elem, rect ); rect->SetFlags( IS_NEW ); @@ -1948,29 +2234,47 @@ void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map& aPro } else { - const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); + LIB_SYMBOL* symbol = aSymbol; + SCH_SYMBOL* schsym = nullptr; - if( libSymbolIt == m_libSymbols.end() ) + if( !aSymbol ) { - // TODO: e.g. can depend on Template (RECORD=39 - m_reporter->Report( wxString::Format( wxT( "Rectangle's owner (%d) not found." ), - elem.OwnerIndex ), - RPT_SEVERITY_DEBUG ); - return; + const auto& libSymbolIt = m_libSymbols.find( elem.OwnerIndex ); + + if( libSymbolIt == m_libSymbols.end() ) + { + // TODO: e.g. can depend on Template (RECORD=39 + m_reporter->Report( wxString::Format( wxT( "Rectangle's owner (%d) not found." ), + elem.OwnerIndex ), + RPT_SEVERITY_DEBUG ); + return; + } + + symbol = libSymbolIt->second; + schsym = m_symbols.at( libSymbolIt->first ); } - if( !IsComponentPartVisible( elem.OwnerIndex, elem.OwnerPartDisplayMode ) ) + if( !aSymbol && !IsComponentPartVisible( elem.OwnerIndex, elem.OwnerPartDisplayMode ) ) return; - SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); - LIB_SHAPE* rect = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::RECTANGLE ); - libSymbolIt->second->AddDrawItem( rect ); + LIB_SHAPE* rect = new LIB_SHAPE( symbol, SHAPE_T::RECTANGLE ); + symbol->AddDrawItem( rect, false ); rect->SetUnit( elem.OwnerPartID ); - rect->SetPosition( GetRelativePosition( sheetTopRight, symbol ) ); - rect->SetEnd( GetRelativePosition( sheetBottomLeft, symbol ) ); - SetLibShapeFillAndColor( elem, rect ); + if( !schsym ) + { + rect->SetPosition( GetLibEditPosition( sheetTopRight ) ); + rect->SetEnd( GetLibEditPosition( sheetBottomLeft ) ); + } + else + { + rect->SetPosition( GetRelativePosition( sheetTopRight, schsym ) ); + rect->SetEnd( GetRelativePosition( sheetBottomLeft, schsym ) ); + } + + SetLibShapeLine( elem, rect, ALTIUM_SCH_RECORD::RECTANGLE ); + SetLibShapeFillAndColor( elem, rect, ALTIUM_SCH_RECORD::RECTANGLE, elem.Color ); } } @@ -2094,7 +2398,7 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE || aStyle == ASCH_POWER_PORT_STYLE::ARROW ) { LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line1 ); + aKsymbol->AddDrawItem( line1, false ); line1->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, schIUScale.MilsToIU( -50 ) } ); @@ -2102,7 +2406,7 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE ) { LIB_SHAPE* circle = new LIB_SHAPE( aKsymbol, SHAPE_T::CIRCLE ); - aKsymbol->AddDrawItem( circle ); + aKsymbol->AddDrawItem( circle, false ); circle->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 5 ), PLOT_DASH_TYPE::SOLID ) ); circle->SetPosition( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( -75 ) } ); circle->SetEnd( circle->GetPosition() + VECTOR2I( schIUScale.MilsToIU( 25 ), 0 ) ); @@ -2110,7 +2414,7 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ else { LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line2 ); + aKsymbol->AddDrawItem( line2, false ); line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { schIUScale.MilsToIU( -25 ), schIUScale.MilsToIU( -50 ) } ); line2->AddPoint( { schIUScale.MilsToIU( 25 ), schIUScale.MilsToIU( -50 ) } ); @@ -2123,13 +2427,13 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ else if( aStyle == ASCH_POWER_PORT_STYLE::WAVE ) { LIB_SHAPE* line = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line ); + aKsymbol->AddDrawItem( line, false ); line->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line->AddPoint( { 0, 0 } ); line->AddPoint( { 0, schIUScale.MilsToIU( -72 ) } ); LIB_SHAPE* bezier = new LIB_SHAPE( aKsymbol, SHAPE_T::BEZIER ); - aKsymbol->AddDrawItem( bezier ); + aKsymbol->AddDrawItem( bezier, false ); bezier->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 5 ), PLOT_DASH_TYPE::SOLID ) ); bezier->AddPoint( { schIUScale.MilsToIU( 30 ), schIUScale.MilsToIU( -50 ) } ); bezier->AddPoint( { schIUScale.MilsToIU( 30 ), schIUScale.MilsToIU( -87 ) } ); @@ -2144,7 +2448,7 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ || aStyle == ASCH_POWER_PORT_STYLE::GOST_ARROW ) { LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line1 ); + aKsymbol->AddDrawItem( line1, false ); line1->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, schIUScale.MilsToIU( -100 ) } ); @@ -2152,25 +2456,25 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND ) { LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line2 ); + aKsymbol->AddDrawItem( line2, false ); line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( -100 ) } ); line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( -100 ) } ); LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line3 ); + aKsymbol->AddDrawItem( line3, false ); line3->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line3->AddPoint( { schIUScale.MilsToIU( -70 ), schIUScale.MilsToIU( -130 ) } ); line3->AddPoint( { schIUScale.MilsToIU( 70 ), schIUScale.MilsToIU( -130 ) } ); LIB_SHAPE* line4 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line4 ); + aKsymbol->AddDrawItem( line4, false ); line4->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line4->AddPoint( { schIUScale.MilsToIU( -40 ), schIUScale.MilsToIU( -160 ) } ); line4->AddPoint( { schIUScale.MilsToIU( 40 ), schIUScale.MilsToIU( -160 ) } ); LIB_SHAPE* line5 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line5 ); + aKsymbol->AddDrawItem( line5, false ); line5->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line5->AddPoint( { schIUScale.MilsToIU( -10 ), schIUScale.MilsToIU( -190 ) } ); line5->AddPoint( { schIUScale.MilsToIU( 10 ), schIUScale.MilsToIU( -190 ) } ); @@ -2178,7 +2482,7 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ else if( aStyle == ASCH_POWER_PORT_STYLE::SIGNAL_GROUND ) { LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line2 ); + aKsymbol->AddDrawItem( line2, false ); line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( -100 ) } ); line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( -100 ) } ); @@ -2188,7 +2492,7 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ else if( aStyle == ASCH_POWER_PORT_STYLE::EARTH ) { LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line2 ); + aKsymbol->AddDrawItem( line2, false ); line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { schIUScale.MilsToIU( -150 ), schIUScale.MilsToIU( -200 ) } ); line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( -100 ) } ); @@ -2196,7 +2500,7 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ line2->AddPoint( { schIUScale.MilsToIU( 50 ), schIUScale.MilsToIU( -200 ) } ); LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line3 ); + aKsymbol->AddDrawItem( line3, false ); line3->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line3->AddPoint( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( -100 ) } ); line3->AddPoint( { schIUScale.MilsToIU( -50 ), schIUScale.MilsToIU( -200 ) } ); @@ -2204,7 +2508,7 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ else // ASCH_POWER_PORT_STYLE::GOST_ARROW { LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line2 ); + aKsymbol->AddDrawItem( line2, false ); line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { schIUScale.MilsToIU( -25 ), schIUScale.MilsToIU( -50 ) } ); line2->AddPoint( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( -100 ) } ); @@ -2219,25 +2523,25 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ || aStyle == ASCH_POWER_PORT_STYLE::GOST_EARTH ) { LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line1 ); + aKsymbol->AddDrawItem( line1, false ); line1->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, schIUScale.MilsToIU( -160 ) } ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line2 ); + aKsymbol->AddDrawItem( line2, false ); line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( -160 ) } ); line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( -160 ) } ); LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line3 ); + aKsymbol->AddDrawItem( line3, false ); line3->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line3->AddPoint( { schIUScale.MilsToIU( -60 ), schIUScale.MilsToIU( -200 ) } ); line3->AddPoint( { schIUScale.MilsToIU( 60 ), schIUScale.MilsToIU( -200 ) } ); LIB_SHAPE* line4 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line4 ); + aKsymbol->AddDrawItem( line4, false ); line4->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line4->AddPoint( { schIUScale.MilsToIU( -20 ), schIUScale.MilsToIU( -240 ) } ); line4->AddPoint( { schIUScale.MilsToIU( 20 ), schIUScale.MilsToIU( -240 ) } ); @@ -2246,7 +2550,7 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ return { 0, schIUScale.MilsToIU( 300 ) }; LIB_SHAPE* circle = new LIB_SHAPE( aKsymbol, SHAPE_T::CIRCLE ); - aKsymbol->AddDrawItem( circle ); + aKsymbol->AddDrawItem( circle, false ); circle->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); circle->SetPosition( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( -160 ) } ); circle->SetEnd( circle->GetPosition() + VECTOR2I( schIUScale.MilsToIU( 120 ), 0 ) ); @@ -2256,13 +2560,13 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_BAR ) { LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line1 ); + aKsymbol->AddDrawItem( line1, false ); line1->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, schIUScale.MilsToIU( -200 ) } ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line2 ); + aKsymbol->AddDrawItem( line2, false ); line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( -200 ) } ); line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( -200 ) } ); @@ -2278,13 +2582,13 @@ VECTOR2I HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_ } LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line1 ); + aKsymbol->AddDrawItem( line1, false ); line1->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line1->AddPoint( { 0, 0 } ); line1->AddPoint( { 0, schIUScale.MilsToIU( -100 ) } ); LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY ); - aKsymbol->AddDrawItem( line2 ); + aKsymbol->AddDrawItem( line2, false ); line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), PLOT_DASH_TYPE::SOLID ) ); line2->AddPoint( { schIUScale.MilsToIU( -50 ), schIUScale.MilsToIU( -100 ) } ); line2->AddPoint( { schIUScale.MilsToIU( 50 ), schIUScale.MilsToIU( -100 ) } ); @@ -2321,7 +2625,7 @@ void SCH_ALTIUM_PLUGIN::ParsePowerPort( const std::map& aPro // generate graphic LIB_PIN* pin = new LIB_PIN( libSymbol ); - libSymbol->AddDrawItem( pin ); + libSymbol->AddDrawItem( pin, false ); pin->SetName( elem.text ); pin->SetPosition( { 0, 0 } ); @@ -2686,11 +2990,11 @@ void SCH_ALTIUM_PLUGIN::ParseImage( const std::map& aPropert { ASCH_IMAGE elem( aProperties ); - const auto& component = m_altiumComponents.find( elem.ownerindex ); + const auto& component = m_altiumComponents.find( elem.OwnerIndex ); //Hide the image if it is owned by a component but the part id do not match if( component != m_altiumComponents.end() - && component->second.currentpartid != elem.ownerpartid ) + && component->second.currentpartid != elem.OwnerPartID ) return; VECTOR2I center = ( elem.location + elem.corner ) / 2 + m_sheetOffset; @@ -2847,17 +3151,34 @@ void SCH_ALTIUM_PLUGIN::ParseFileName( const std::map& aProp } -void SCH_ALTIUM_PLUGIN::ParseDesignator( const std::map& aProperties ) +void SCH_ALTIUM_PLUGIN::ParseDesignator( const std::map& aProperties, + LIB_SYMBOL* aSymbol ) { ASCH_DESIGNATOR elem( aProperties ); + if( aSymbol ) + { + bool emptyRef = elem.text.IsEmpty(); + LIB_FIELD& refField = aSymbol->GetReferenceField(); + + if( emptyRef ) + refField.SetText( wxT( "X?" ) ); + else + refField.SetText( elem.text ); + + refField.SetPosition( elem.location ); + + return; + } + + const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex ); if( libSymbolIt == m_libSymbols.end() ) { // TODO: e.g. can depend on Template (RECORD=39 m_reporter->Report( wxString::Format( wxT( "Designator's owner (%d) not found." ), - elem.ownerindex ), + elem.ownerindex ), RPT_SEVERITY_DEBUG ); return; } @@ -2903,20 +3224,18 @@ void SCH_ALTIUM_PLUGIN::ParseBusEntry( const std::map& aProp } -void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map& aProperties ) +void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map& aProperties, + LIB_SYMBOL* aSymbol ) { ASCH_PARAMETER elem( aProperties ); - SCH_SCREEN* screen = getCurrentScreen(); - wxCHECK( screen, /* void */ ); - // TODO: fill in replacements from variant, sheet and project std::map variableMap = { { "COMMENT", "VALUE" }, { "VALUE", "ALTIUM_VALUE" }, }; - if( elem.ownerindex <= 0 && elem.ownerpartid == ALTIUM_COMPONENT_NONE ) + if( !aSymbol && elem.ownerindex <= 0 && elem.ownerpartid == ALTIUM_COMPONENT_NONE ) { // This is some sheet parameter if( elem.text == "*" ) @@ -2951,47 +3270,93 @@ void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map& aPro } else { - const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex ); + LIB_SYMBOL* libSymbol = aSymbol; + SCH_SYMBOL* symbol = nullptr; - if( libSymbolIt == m_libSymbols.end() ) + if( !aSymbol ) { - // TODO: e.g. can depend on Template (RECORD=39 - return; + const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex ); + + if( libSymbolIt == m_libSymbols.end() ) + { + // TODO: e.g. can depend on Template (RECORD=39 + return; + } + + libSymbol = libSymbolIt->second; + symbol = m_symbols.at( libSymbolIt->first ); } - SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first ); - SCH_FIELD* field = nullptr; + EDA_TEXT* field = nullptr; wxString upperName = elem.name.Upper(); if( upperName == "COMMENT" ) { - field = symbol->GetField( VALUE_FIELD ); + if( !symbol ) + field = &libSymbol->GetValueField(); + else + field = symbol->GetField( VALUE_FIELD ); } else { - int fieldIdx = symbol->GetFieldCount(); + int fieldIdx = 0; wxString fieldName = elem.name.Upper(); + if( !symbol ) + fieldIdx = libSymbol->GetFieldCount(); + else + fieldIdx = symbol->GetFieldCount(); + if( fieldName.IsEmpty() ) { int disambiguate = 1; - do + while( 1 ) { fieldName = wxString::Format( "ALTIUM_UNNAMED_%d", disambiguate++ ); - } while( !symbol->GetFieldText( fieldName ).IsEmpty() ); + + if( symbol ) + { + if( !symbol->FindField( fieldName ) ) + break; + } + else + { + if( !libSymbol->FindField( fieldName ) ) + break; + } + } } else if( fieldName == "VALUE" ) { fieldName = "ALTIUM_VALUE"; } - field = symbol->AddField( SCH_FIELD( VECTOR2I(), fieldIdx, symbol, fieldName ) ); + if( !symbol ) + { + LIB_FIELD* new_field = new LIB_FIELD( fieldIdx, fieldName ); + libSymbol->AddField( new_field ); + field = new_field; + } + else + { + field = symbol->AddField( SCH_FIELD( VECTOR2I(), fieldIdx, symbol, fieldName ) ); + } } wxString kicadText = AltiumSpecialStringsToKiCadVariables( elem.text, variableMap ); field->SetText( kicadText ); - field->SetPosition( elem.location + m_sheetOffset ); + + if( !symbol ) + { + field->SetTextPos( elem.location ); + SetTextPositioning( field, elem.justification, elem.orientation ); + } + else + { + static_cast( field )->SetPosition( elem.location + m_sheetOffset ); + } + field->SetVisible( !elem.isHidden ); SetTextPositioning( field, elem.justification, elem.orientation ); } @@ -3045,3 +3410,295 @@ void SCH_ALTIUM_PLUGIN::ParseImplementation( const std::map& symbol->SetFootprintFieldText( fpLibId.Format() ); } } + + + +LIB_SYMBOL* SCH_ALTIUM_PLUGIN::ParseLibComponent( const std::map& aProperties ) +{ + ASCH_SYMBOL elem( aProperties ); + + LIB_ID libId = AltiumToKiCadLibID( getLibName(), elem.libreference ); + + LIB_SYMBOL* ksymbol = new LIB_SYMBOL( wxEmptyString ); + ksymbol->SetName( elem.libreference ); + ksymbol->SetDescription( elem.componentdescription ); + ksymbol->SetLibId( libId ); + ksymbol->SetUnitCount( elem.partcount - 1 ); + + return ksymbol; +} + + +std::map SCH_ALTIUM_PLUGIN::ParseLibFile( const ALTIUM_COMPOUND_FILE& aAltiumSchFile ) +{ + std::map ret; + + { + const CFB::COMPOUND_FILE_ENTRY* file = aAltiumSchFile.FindStream( { "FileHeader" } ); + + if( file == nullptr ) + THROW_IO_ERROR( "FileHeader not found" ); + + ALTIUM_PARSER reader( aAltiumSchFile, file ); + + if( reader.GetRemainingBytes() <= 0 ) + { + THROW_IO_ERROR( "FileHeader does not contain any data" ); + } + } + + std::map syms = aAltiumSchFile.GetLibSymbols( nullptr ); + + for( auto& [name, entry] : syms ) + { + ALTIUM_PARSER reader( aAltiumSchFile, entry ); + LIB_SYMBOL* symbol = nullptr; + + if( reader.GetRemainingBytes() <= 0 ) + { + THROW_IO_ERROR( "LibSymbol does not contain any data" ); + } + + { + std::map properties = reader.ReadProperties(); + int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", 0 ); + ALTIUM_SCH_RECORD record = static_cast( recordId ); + + if( record != ALTIUM_SCH_RECORD::COMPONENT ) + THROW_IO_ERROR( "LibSymbol does not start with COMPONENT record" ); + + symbol = ParseLibComponent( properties ); + } + + auto handleBinaryDataLambda = + []( const std::string& binaryData ) -> std::map + { + + std::map result; + + ALTIUM_BINARY_READER binreader( binaryData ); + + int32_t recordId = binreader.ReadInt32(); + + if( recordId != static_cast( ALTIUM_SCH_RECORD::PIN ) ) + THROW_IO_ERROR( "Binary record missing PIN record" ); + + result["RECORD"] = wxString::Format( "%d", recordId ); + binreader.ReadByte(); // unknown + result["OWNERPARTID"] = wxString::Format( "%d", binreader.ReadInt16() ); + result["OWNERPARTDISPLAYMODE"] = wxString::Format( "%d", binreader.ReadByte() ); + result["SYMBOL_INNEREDGE"] = wxString::Format( "%d", binreader.ReadByte() ); + result["SYMBOL_OUTEREDGE"] = wxString::Format( "%d", binreader.ReadByte() ); + result["SYMBOL_INNER"] = wxString::Format( "%d", binreader.ReadByte() ); + result["SYMBOL_OUTER"] = wxString::Format( "%d", binreader.ReadByte() ); + result["TEXT"] = binreader.ReadPascalString(); + binreader.ReadByte(); // unknown + result["ELECTRICAL"] = wxString::Format( "%d", binreader.ReadByte() ); + result["PINCONGLOMERATE"] = wxString::Format( "%d", binreader.ReadByte() ); + result["PINLENGTH"] = wxString::Format( "%d", binreader.ReadInt16() ); + result["LOCATION.X"] = wxString::Format( "%d", binreader.ReadInt16() ); + result["LOCATION.Y"] = wxString::Format( "%d", binreader.ReadInt16() ); + result["COLOR"] = wxString::Format( "%d", binreader.ReadInt32() ); + result["NAME"] = binreader.ReadPascalString(); + result["DESIGNATOR"] = binreader.ReadPascalString(); + result["SWAPIDGROUP"] = binreader.ReadPascalString(); + + std::string partSeq = binreader.ReadPascalString(); // This is 'part|&|seq' + std::vector partSeqSplit = split( partSeq, "|" ); + + if( partSeqSplit.size() == 3 ) + { + result["PART"] = partSeqSplit[0]; + result["SEQ"] = partSeqSplit[2]; + } + + // Mark the pin as belonging to a library symbol, so we can adjust the coordinates + // as needed for KiCad's symbol editor + result["ISKICADLIBPIN"] = wxString( "T" ); + return result; + }; + + while( reader.GetRemainingBytes() > 0 ) + { + std::map properties = reader.ReadProperties( handleBinaryDataLambda ); + + if( properties.empty() ) + continue; + + int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", 0 ); + ALTIUM_SCH_RECORD record = static_cast( recordId ); + + switch( record ) + { + case ALTIUM_SCH_RECORD::PIN: ParsePin( properties, symbol ); break; + + case ALTIUM_SCH_RECORD::LABEL: ParseLabel( properties, symbol ); break; + + case ALTIUM_SCH_RECORD::BEZIER: ParseBezier( properties, symbol ); break; + + case ALTIUM_SCH_RECORD::POLYLINE: ParsePolyline( properties, symbol ); break; + + case ALTIUM_SCH_RECORD::POLYGON: ParsePolygon( properties, symbol ); break; + + case ALTIUM_SCH_RECORD::ELLIPSE: ParseEllipse( properties, symbol ); break; + + case ALTIUM_SCH_RECORD::ROUND_RECTANGLE: ParseRoundRectangle( properties, symbol ); break; + + case ALTIUM_SCH_RECORD::ELLIPTICAL_ARC: + case ALTIUM_SCH_RECORD::ARC: ParseArc( properties, symbol ); break; + + case ALTIUM_SCH_RECORD::LINE: ParseLine( properties, symbol ); break; + + case ALTIUM_SCH_RECORD::RECTANGLE: ParseRectangle( properties, symbol ); break; + + case ALTIUM_SCH_RECORD::DESIGNATOR: ParseDesignator( properties, symbol ); break; + + case ALTIUM_SCH_RECORD::PARAMETER: ParseParameter( properties, symbol ); break; + + case ALTIUM_SCH_RECORD::TEXT_FRAME: ParseTextFrame( properties, symbol ); break; + + // Nothing for now. TODO: Figure out how implementation lists are generted in libs + case ALTIUM_SCH_RECORD::IMPLEMENTATION_LIST: break; + + default: + m_reporter->Report( wxString::Format( _( "Unknown or unexpected record id %d found " + "inside \"Data\" section." ), + recordId ), + RPT_SEVERITY_ERROR ); + break; + } + } + + if( reader.HasParsingError() ) + THROW_IO_ERROR( "stream was not parsed correctly!" ); + + if( reader.GetRemainingBytes() != 0 ) + THROW_IO_ERROR( "stream is not fully parsed" ); + + ret[name] = symbol; + } + + return ret; +} + + +long long SCH_ALTIUM_PLUGIN::getLibraryTimestamp( const wxString& aLibraryPath ) const +{ + wxFileName fn( aLibraryPath ); + + if( fn.IsFileReadable() ) + return fn.GetModificationTime().GetValue().GetValue(); + else + return wxDateTime( 0.0 ).GetValue().GetValue(); +} + + +void SCH_ALTIUM_PLUGIN::ensureLoadedLibrary( const wxString& aLibraryPath, + const STRING_UTF8_MAP* aProperties ) +{ + if( m_libCache.count( aLibraryPath ) ) + { + wxCHECK( m_timestamps.count( aLibraryPath ), /*void*/ ); + + if( m_timestamps.at( aLibraryPath ) == getLibraryTimestamp( aLibraryPath ) ) + return; + } + + ALTIUM_COMPOUND_FILE altiumSchFile( aLibraryPath ); + + wxFileName fileName( aLibraryPath ); + m_libName = fileName.GetName(); + + try + { + std::map ret = ParseLibFile( altiumSchFile ); + m_libCache[aLibraryPath] = ret; + m_timestamps[aLibraryPath] = getLibraryTimestamp( aLibraryPath ); + } + catch( const CFB::CFBException& exception ) + { + THROW_IO_ERROR( exception.what() ); + } + catch( const std::exception& exc ) + { + wxLogDebug( wxT( "Unhandled exception in Altium schematic parsers: %s." ), exc.what() ); + throw; + } +} + + +void SCH_ALTIUM_PLUGIN::ParseLibHeader( const ALTIUM_COMPOUND_FILE& aAltiumSchFile, + wxArrayString& aSymbolNameList ) +{ + const CFB::COMPOUND_FILE_ENTRY* file = aAltiumSchFile.FindStream( { "FileHeader" } ); + + if( file == nullptr ) + THROW_IO_ERROR( "FileHeader not found" ); + + ALTIUM_PARSER reader( aAltiumSchFile, file ); + + if( reader.GetRemainingBytes() <= 0 ) + { + THROW_IO_ERROR( "FileHeader does not contain any data" ); + } + else + { + std::map properties = reader.ReadProperties(); + + wxString libtype = ALTIUM_PARSER::ReadString( properties, "HEADER", "" ); + + if( libtype != "Protel for Windows - Schematic Library Editor Binary File Version 5.0" ) + THROW_IO_ERROR( _( "Expected Altium Schematic Library file version 5.0" ) ); + + for( auto& [key, value] : properties ) + { + if( key.StartsWith( "LibRef" ) ) + { + aSymbolNameList.Add( value ); + } + } + } +} + + +void SCH_ALTIUM_PLUGIN::EnumerateSymbolLib( wxArrayString& aSymbolNameList, + const wxString& aLibraryPath, + const STRING_UTF8_MAP* aProperties ) +{ + ParseLibHeader( aLibraryPath, aSymbolNameList ); +} + + +void SCH_ALTIUM_PLUGIN::EnumerateSymbolLib( std::vector& aSymbolList, + const wxString& aLibraryPath, + const STRING_UTF8_MAP* aProperties ) +{ + ensureLoadedLibrary( aLibraryPath, aProperties ); + + auto it = m_libCache.find( aLibraryPath ); + + if( it != m_libCache.end() ) + { + for( auto& [libnameStr, libSymbol] : it->second ) + aSymbolList.push_back( libSymbol ); + } +} + +LIB_SYMBOL* SCH_ALTIUM_PLUGIN::LoadSymbol( const wxString& aLibraryPath, + const wxString& aAliasName, + const STRING_UTF8_MAP* aProperties ) +{ + ensureLoadedLibrary( aLibraryPath, aProperties ); + + auto it = m_libCache.find( aLibraryPath ); + + if( it != m_libCache.end() ) + { + auto it2 = it->second.find( aAliasName ); + + if( it2 != it->second.end() ) + return it2->second; + } + + return nullptr; +} \ No newline at end of file diff --git a/eeschema/sch_plugins/altium/sch_altium_plugin.h b/eeschema/sch_plugins/altium/sch_altium_plugin.h index a82fafafff..ec9d7775e5 100644 --- a/eeschema/sch_plugins/altium/sch_altium_plugin.h +++ b/eeschema/sch_plugins/altium/sch_altium_plugin.h @@ -60,10 +60,10 @@ public: return PLUGIN_FILE_DESC( _HKI( "Altium schematic files" ), { "SchDoc" } ); } - /*const PLUGIN_FILE_DESC GetLibraryFileDesc() const override + const PLUGIN_FILE_DESC GetLibraryFileDesc() const override { return PLUGIN_FILE_DESC( _HKI( "Altium schematic library files" ), { "SchLib" } ); - }*/ + } int GetModifyHash() const override; @@ -77,11 +77,17 @@ public: //void Save( const wxString& aFileName, SCH_SCREEN* aSchematic, KIWAY* aKiway, // const PROPERTIES* aProperties = NULL ) override; - //void EnumerateSymbolLib( wxArrayString& aAliasNameList, const wxString& aLibraryPath, - // const PROPERTIES* aProperties = NULL ) override; - //LIB_SYMBOL* LoadSymbol( const wxString& aLibraryPath, const wxString& aAliasName, - // const PROPERTIES* aProperties = NULL ) override; + void EnumerateSymbolLib( wxArrayString& aSymbolNameList, + const wxString& aLibraryPath, + const STRING_UTF8_MAP* aProperties = nullptr ) override; + + void EnumerateSymbolLib( std::vector& aSymbolList, + const wxString& aLibraryPath, + const STRING_UTF8_MAP* aProperties = nullptr ) override; + + LIB_SYMBOL* LoadSymbol( const wxString& aLibraryPath, const wxString& aAliasName, + const STRING_UTF8_MAP* aProperties = nullptr ) override; //void SaveSymbol( const wxString& aLibraryPath, const LIB_SYMBOL* aSymbol, // const PROPERTIES* aProperties = NULL ) override; @@ -98,7 +104,10 @@ public: // bool DeleteSymbolLib( const wxString& aLibraryPath, // const PROPERTIES* aProperties = NULL ) override; - //bool IsSymbolLibWritable( const wxString& aLibraryPath ) override; + bool IsSymbolLibWritable( const wxString& aLibraryPath ) override + { + return false; + } //void SymbolLibOptions( PROPERTIES* aListToAppendTo ) const override; @@ -117,25 +126,27 @@ private: bool IsComponentPartVisible( int aOwnerindex, int aOwnerpartdisplaymode ) const; const ASCH_STORAGE_FILE* GetFileFromStorage( const wxString& aFilename ) const; void AddTextBox( const ASCH_TEXT_FRAME* aElem ); + void AddLibTextBox( const ASCH_TEXT_FRAME* aElem, LIB_SYMBOL* aLibSymbol = nullptr ); void ParseComponent( int aIndex, const std::map& aProperties ); - void ParsePin( const std::map& aProperties ); - void ParseLabel( const std::map& aProperties ); - void ParseTextFrame( const std::map& aProperties ); + void ParsePin( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); + void ParseLabel( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); + void ParseTextFrame( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); void ParseNote( const std::map& aProperties ); - void ParseBezier( const std::map& aProperties ); - void ParsePolyline( const std::map& aProperties ); - void ParsePolygon( const std::map& aProperties ); - void ParseRoundRectangle( const std::map& aProperties ); - void ParseArc( const std::map& aProperties ); - void ParseEllipse( const std::map& aProperties ); - void ParseLine( const std::map& aProperties ); + void ParseBezier( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); + void ParsePolyline( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); + void ParsePolygon( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); + void ParseRoundRectangle( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); + void ParseArc( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); + void ParseEllipse( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); + void ParseLine( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); void ParseSignalHarness( const std::map& aProperties ); void ParseHarnessConnector( int aIndex, const std::map& aProperties ); void ParseHarnessEntry( const std::map& aProperties ); void ParseHarnessType( const std::map& aProperties ); void ParseHarnessPort( const ASCH_PORT& aElem ); - void ParseRectangle( const std::map& aProperties ); + void ParseHyperlink( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); + void ParseRectangle( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); void ParseSheetSymbol( int aIndex, const std::map& aProperties ); void ParseSheetEntry( const std::map& aProperties ); void ParsePowerPort( const std::map& aProperties ); @@ -149,12 +160,16 @@ private: void ParseSheet( const std::map& aProperties ); void ParseSheetName( const std::map& aProperties ); void ParseFileName( const std::map& aProperties ); - void ParseDesignator( const std::map& aProperties ); + void ParseDesignator( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); void ParseBusEntry( const std::map& aProperties ); - void ParseParameter( const std::map& aProperties ); + void ParseParameter( const std::map& aProperties, LIB_SYMBOL* aLibSymbol = nullptr ); void ParseImplementationList( int aIndex, const std::map& aProperties ); void ParseImplementation( const std::map& aProperties ); + void ParseLibHeader( const ALTIUM_COMPOUND_FILE& aAltiumSchFile, wxArrayString& aLibNames ); + std::map ParseLibFile( const ALTIUM_COMPOUND_FILE& aAltiumSchFile ); + LIB_SYMBOL* ParseLibComponent( const std::map& aProperties ); + private: REPORTER* m_reporter; // current reporter for warnings/errors @@ -189,6 +204,13 @@ private: // Add offset to all harness ownerIndex'es after parsing FileHeader. int m_harnessOwnerIndexOffset; int m_harnessEntryParent; // used to identify harness connector for harness entry element + + // Symbol caching + void ensureLoadedLibrary( const wxString& aLibraryPath, const STRING_UTF8_MAP* aProperties ); + long long getLibraryTimestamp( const wxString& aLibraryPath ) const; + + std::map m_timestamps; + std::map> m_libCache; }; #endif // _SCH_ALTIUM_PLUGIN_H_