KiCad PCB EDA Suite
sch_altium_plugin.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2020 Thomas Pointhuber <[email protected]>
5  * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <memory>
26 
27 #include "altium_parser_sch.h"
31 
32 #include <schematic.h>
33 
34 #include <lib_shape.h>
35 #include <lib_id.h>
36 #include <lib_item.h>
37 #include <lib_pin.h>
38 #include <lib_text.h>
39 
40 #include <sch_bitmap.h>
41 #include <sch_bus_entry.h>
42 #include <sch_symbol.h>
43 #include <sch_junction.h>
44 #include <sch_line.h>
45 #include <sch_no_connect.h>
46 #include <sch_screen.h>
47 #include <sch_sheet.h>
48 #include <sch_sheet_pin.h>
49 #include <sch_text.h>
50 
51 #include <bezier_curves.h>
52 #include <compoundfilereader.h>
53 #include <string_utils.h>
54 #include <sch_edit_frame.h>
55 #include <trigo.h>
57 #include <wx/mstream.h>
58 #include <wx/log.h>
59 #include <wx/zstream.h>
60 #include <wx/wfstream.h>
61 #include <trigo.h>
62 
63 const wxPoint GetRelativePosition( const wxPoint& aPosition, const SCH_SYMBOL* aSymbol )
64 {
65  TRANSFORM t = aSymbol->GetTransform().InverseTransform();
66  return t.TransformCoordinate( aPosition - aSymbol->GetPosition() );
67 }
68 
69 
71 {
72  int red = color & 0x0000FF;
73  int green = ( color & 0x00FF00 ) >> 8;
74  int blue = ( color & 0xFF0000 ) >> 16;
75 
76  return COLOR4D().FromCSSRGBA( red, green, blue, 1.0 );
77 }
78 
80 {
81  m_rootSheet = nullptr;
82  m_currentSheet = nullptr;
83  m_schematic = nullptr;
84 
86 }
87 
88 
90 {
91 }
92 
93 
94 const wxString SCH_ALTIUM_PLUGIN::GetName() const
95 {
96  return wxT( "Altium" );
97 }
98 
99 
101 {
102  return wxT( "SchDoc" );
103 }
104 
105 
107 {
108  return wxT( "SchLib" );
109 }
110 
111 
113 {
114  return 0;
115 }
116 
117 
118 bool SCH_ALTIUM_PLUGIN::CheckHeader( const wxString& aFileName )
119 {
120  // TODO
121 
122  return true;
123 }
124 
125 
127 {
128  if( m_libName.IsEmpty() )
129  {
130  // Try to come up with a meaningful name
132 
133  if( m_libName.IsEmpty() )
134  {
135  wxFileName fn( m_rootSheet->GetFileName() );
136  m_libName = fn.GetName();
137  }
138 
139  if( m_libName.IsEmpty() )
140  m_libName = wxT( "noname" );
141 
142  m_libName += wxT( "-altium-import" );
144  }
145 
146  return m_libName;
147 }
148 
149 
151 {
153 
154  return fn;
155 }
156 
157 
158 SCH_SHEET* SCH_ALTIUM_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchematic,
159  SCH_SHEET* aAppendToMe, const PROPERTIES* aProperties )
160 {
161  wxASSERT( !aFileName || aSchematic != nullptr );
162 
163  wxFileName fileName( aFileName );
164  fileName.SetExt( KiCadSchematicFileExtension );
165  m_schematic = aSchematic;
166 
167  // Delete on exception, if I own m_rootSheet, according to aAppendToMe
168  std::unique_ptr<SCH_SHEET> deleter( aAppendToMe ? nullptr : m_rootSheet );
169 
170  if( aAppendToMe )
171  {
172  wxCHECK_MSG( aSchematic->IsValid(), nullptr, wxT( "Can't append to a schematic with no root!" ) );
173  m_rootSheet = &aSchematic->Root();
174  }
175  else
176  {
177  m_rootSheet = new SCH_SHEET( aSchematic );
178  m_rootSheet->SetFileName( fileName.GetFullPath() );
179 
180  aSchematic->SetRoot( m_rootSheet );
181 
182  SCH_SHEET_PATH sheetpath;
183  sheetpath.push_back( m_rootSheet );
184 
185  m_rootSheet->AddInstance( sheetpath );
186  m_rootSheet->SetPageNumber( sheetpath, wxT( "#" ) ); // We'll update later if we find a
187  // pageNumber record for it
188  }
189 
190  if( !m_rootSheet->GetScreen() )
191  {
192  SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
193  screen->SetFileName( aFileName );
194  m_rootSheet->SetScreen( screen );
195  }
196 
197  SYMBOL_LIB_TABLE* libTable = m_schematic->Prj().SchSymbolLibTable();
198 
199  wxCHECK_MSG( libTable, nullptr, wxT( "Could not load symbol lib table." ) );
200 
201  m_pi.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
202 
205  if( !libTable->HasLibrary( getLibName() ) )
206  {
207  // Create a new empty symbol library.
208  m_pi->CreateSymbolLib( getLibFileName().GetFullPath() );
209  wxString libTableUri = wxT( "${KIPRJMOD}/" ) + getLibFileName().GetFullName();
210 
211  // Add the new library to the project symbol library table.
212  libTable->InsertRow( new SYMBOL_LIB_TABLE_ROW( getLibName(), libTableUri,
213  wxString( wxT( "KiCad" ) ) ) );
214 
215  // Save project symbol library table.
216  wxFileName fn( m_schematic->Prj().GetProjectPath(),
218 
219  // So output formatter goes out of scope and closes the file before reloading.
220  {
221  FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() );
222  libTable->Format( &formatter, 0 );
223  }
224 
225  // Reload the symbol library table.
227  m_schematic->Prj().SchSymbolLibTable();
228  }
229 
231  ParseAltiumSch( aFileName );
232 
233  m_pi->SaveLibrary( getLibFileName().GetFullPath() );
234 
235  SCH_SCREENS allSheets( m_rootSheet );
236  allSheets.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
237  allSheets.ClearEditFlags();
238 
239  return m_rootSheet;
240 }
241 
242 
243 void SCH_ALTIUM_PLUGIN::ParseAltiumSch( const wxString& aFileName )
244 {
245  // Open file
246  FILE* fp = wxFopen( aFileName, wxT( "rb" ) );
247 
248  if( fp == nullptr )
249  {
250  m_reporter->Report( wxString::Format( _( "Cannot open file '%s'." ), aFileName ),
252  return;
253  }
254 
255  fseek( fp, 0, SEEK_END );
256  long len = ftell( fp );
257 
258  if( len < 0 )
259  {
260  fclose( fp );
261  THROW_IO_ERROR( wxT( "Read error, cannot determine length of file." ) );
262  }
263 
264  std::unique_ptr<unsigned char[]> buffer( new unsigned char[len] );
265  fseek( fp, 0, SEEK_SET );
266 
267  size_t bytesRead = fread( buffer.get(), sizeof( unsigned char ), len, fp );
268  fclose( fp );
269 
270  if( static_cast<size_t>( len ) != bytesRead )
271  THROW_IO_ERROR( wxT( "Read error." ) );
272 
273  try
274  {
275  CFB::CompoundFileReader reader( buffer.get(), bytesRead );
276  ParseStorage( reader ); // we need this before parsing the FileHeader
277  ParseFileHeader( reader );
278  }
279  catch( CFB::CFBException& exception )
280  {
281  THROW_IO_ERROR( exception.what() );
282  }
283 }
284 
285 
286 void SCH_ALTIUM_PLUGIN::ParseStorage( const CFB::CompoundFileReader& aReader )
287 {
288  const CFB::COMPOUND_FILE_ENTRY* file = FindStream( aReader, "Storage" );
289 
290  if( file == nullptr )
291  return;
292 
293  ALTIUM_PARSER reader( aReader, file );
294 
295  std::map<wxString, wxString> properties = reader.ReadProperties();
296  wxString header = ALTIUM_PARSER::ReadString( properties, wxT( "HEADER" ), wxEmptyString );
297  int weight = ALTIUM_PARSER::ReadInt( properties, wxT( "WEIGHT" ), 0 );
298 
299  if( weight < 0 )
300  THROW_IO_ERROR( wxT( "Storage weight is negative!" ) );
301 
302  for( int i = 0; i < weight; i++ )
303  {
304  m_altiumStorage.emplace_back( reader );
305  }
306 
307  if( reader.HasParsingError() )
308  THROW_IO_ERROR( wxT( "stream was not parsed correctly!" ) );
309 
310  // TODO pointhi: is it possible to have multiple headers in one Storage file? Otherwise
311  // throw IO Error.
312  if( reader.GetRemainingBytes() != 0 )
313  {
314  m_reporter->Report( wxString::Format( _( "Storage file not fully parsed "
315  wxT( "(%d bytes remaining)." ) ),
316  reader.GetRemainingBytes() ),
318  }
319 }
320 
321 
322 void SCH_ALTIUM_PLUGIN::ParseFileHeader( const CFB::CompoundFileReader& aReader )
323 {
324  const CFB::COMPOUND_FILE_ENTRY* file = FindStream( aReader, "FileHeader" );
325 
326  if( file == nullptr )
327  THROW_IO_ERROR( wxT( "FileHeader not found" ) );
328 
329  ALTIUM_PARSER reader( aReader, file );
330 
331  if( reader.GetRemainingBytes() <= 0 )
332  {
333  THROW_IO_ERROR( wxT( "FileHeader does not contain any data" ) );
334  }
335  else
336  {
337  std::map<wxString, wxString> properties = reader.ReadProperties();
338 
339  int recordId = ALTIUM_PARSER::ReadInt( properties, wxT( "RECORD" ), 0 );
340  ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
341 
342  if( record != ALTIUM_SCH_RECORD::HEADER )
343  THROW_IO_ERROR( wxT( "Header expected" ) );
344  }
345 
346  // Prepare some local variables
347  wxASSERT( m_altiumPortsCurrentSheet.empty() );
348  wxASSERT( !m_currentTitleBlock );
349 
350  m_currentTitleBlock = std::make_unique<TITLE_BLOCK>();
351 
352  // index is required to resolve OWNERINDEX
353  for( int index = 0; reader.GetRemainingBytes() > 0; index++ )
354  {
355  std::map<wxString, wxString> properties = reader.ReadProperties();
356 
357  int recordId = ALTIUM_PARSER::ReadInt( properties, wxT( "RECORD" ), 0 );
358  ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
359 
360  // see: https://github.com/vadmium/python-altium/blob/master/format.md
361  switch( record )
362  {
364  THROW_IO_ERROR( wxT( "Header already parsed" ) );
366  ParseComponent( index, properties );
367  break;
369  ParsePin( properties );
370  break;
372  break;
374  ParseLabel( properties );
375  break;
377  ParseBezier( properties );
378  break;
380  ParsePolyline( properties );
381  break;
383  ParsePolygon( properties );
384  break;
386  break;
388  break;
390  ParseRoundRectangle( properties );
391  break;
393  break;
395  ParseArc( properties );
396  break;
398  ParseLine( properties );
399  break;
401  ParseRectangle( properties );
402  break;
404  ParseSheetSymbol( index, properties );
405  break;
407  ParseSheetEntry( properties );
408  break;
410  ParsePowerPort( properties );
411  break;
413  // Ports are parsed after the sheet was parsed
414  // This is required because we need all electrical connection points before placing.
415  m_altiumPortsCurrentSheet.emplace_back( properties );
416  break;
418  ParseNoERC( properties );
419  break;
421  ParseNetLabel( properties );
422  break;
424  ParseBus( properties );
425  break;
427  ParseWire( properties );
428  break;
430  ParseTextFrame( properties );
431  break;
433  ParseJunction( properties );
434  break;
436  ParseImage( properties );
437  break;
439  ParseSheet( properties );
440  break;
442  ParseSheetName( properties );
443  break;
445  ParseFileName( properties );
446  break;
448  ParseDesignator( properties );
449  break;
451  ParseBusEntry( properties );
452  break;
454  break;
456  ParseParameter( properties );
457  break;
459  break;
461  ParseImplementationList( index, properties );
462  break;
464  ParseImplementation( properties );
465  break;
467  break;
469  break;
471  break;
473  ParseNote( properties );
474  break;
476  m_reporter->Report( _( "Compile mask not currently supported." ), RPT_SEVERITY_ERROR );
477  break;
479  break;
481  break;
483  break;
485  break;
487  break;
488  default:
489  m_reporter->Report( wxString::Format( _( "Unknown Record id: %d." ), recordId ),
491  break;
492  }
493  }
494 
495  if( reader.HasParsingError() )
496  THROW_IO_ERROR( wxT( "stream was not parsed correctly!" ) );
497 
498  if( reader.GetRemainingBytes() != 0 )
499  THROW_IO_ERROR( wxT( "stream is not fully parsed" ) );
500 
501  // assign LIB_SYMBOL -> COMPONENT
502  for( std::pair<const int, SCH_SYMBOL*>& symbol : m_symbols )
503  {
504  auto libSymbolIt = m_libSymbols.find( symbol.first );
505 
506  if( libSymbolIt == m_libSymbols.end() )
507  THROW_IO_ERROR( wxT( "every symbol should have a symbol attached" ) );
508 
509  m_pi->SaveSymbol( getLibFileName().GetFullPath(),
510  new LIB_SYMBOL( *( libSymbolIt->second ) ), m_properties.get() );
511 
512  symbol.second->SetLibSymbol( libSymbolIt->second );
513  }
514 
515  // Handle title blocks
517  m_currentTitleBlock.reset();
518 
519  // Handle Ports
520  for( const ASCH_PORT& port : m_altiumPortsCurrentSheet )
521  ParsePort( port );
522 
524 
525  m_symbols.clear();
526  m_libSymbols.clear();
527 
528  // Otherwise we cannot save the imported sheet?
530 }
531 
532 
533 bool SCH_ALTIUM_PLUGIN::IsComponentPartVisible( int aOwnerindex, int aOwnerpartdisplaymode ) const
534 {
535  const auto& component = m_altiumComponents.find( aOwnerindex );
536 
537  if( component == m_altiumComponents.end() )
538  return false;
539 
540  return component->second.displaymode == aOwnerpartdisplaymode;
541 }
542 
543 
544 const ASCH_STORAGE_FILE* SCH_ALTIUM_PLUGIN::GetFileFromStorage( const wxString& aFilename ) const
545 {
546  const ASCH_STORAGE_FILE* nonExactMatch = nullptr;
547 
548  for( const ASCH_STORAGE_FILE& file : m_altiumStorage )
549  {
550  if( file.filename.IsSameAs( aFilename ) )
551  return &file;
552 
553  if( file.filename.EndsWith( aFilename ) )
554  nonExactMatch = &file;
555  }
556 
557  return nonExactMatch;
558 }
559 
560 
562  const std::map<wxString, wxString>& aProperties )
563 {
564  auto pair = m_altiumComponents.insert( { aIndex, ASCH_SYMBOL( aProperties ) } );
565  const ASCH_SYMBOL& elem = pair.first->second;
566 
567  // TODO: this is a hack until we correctly apply all transformations to every element
568  wxString name = wxString::Format( wxT( "%d%s_%s" ),
569  elem.orientation,
570  elem.isMirrored ? wxT( "_mirrored" ) : wxEmptyString,
571  elem.libreference );
573 
574  LIB_SYMBOL* ksymbol = new LIB_SYMBOL( wxEmptyString );
575  ksymbol->SetName( name );
576  ksymbol->SetDescription( elem.componentdescription );
577  ksymbol->SetLibId( libId );
578  m_libSymbols.insert( { aIndex, ksymbol } );
579 
580  // each component has its own symbol for now
581  SCH_SYMBOL* symbol = new SCH_SYMBOL();
582 
583  symbol->SetPosition( elem.location + m_sheetOffset );
584 
585  // TODO: keep it simple for now, and only set position.
586  //component->SetOrientation( elem.orientation );
587  symbol->SetLibId( libId );
588 
589  symbol->SetUnit( elem.currentpartid );
590 
591  m_currentSheet->GetScreen()->Append( symbol );
592 
593  m_symbols.insert( { aIndex, symbol } );
594 }
595 
596 
597 void SCH_ALTIUM_PLUGIN::ParsePin( const std::map<wxString, wxString>& aProperties )
598 {
599  ASCH_PIN elem( aProperties );
600 
601  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
602 
603  if( libSymbolIt == m_libSymbols.end() )
604  {
605  // TODO: e.g. can depend on Template (RECORD=39
606  m_reporter->Report( wxString::Format( _( "Pin's owner (%d) not found." ), elem.ownerindex ),
608  return;
609  }
610 
612  return;
613 
614  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
615  LIB_PIN* pin = new LIB_PIN( libSymbolIt->second );
616  libSymbolIt->second->AddDrawItem( pin );
617 
618  pin->SetUnit( elem.ownerpartid );
619 
620  pin->SetName( elem.name );
621  pin->SetNumber( elem.designator );
622  pin->SetLength( elem.pinlength );
623 
624  if( !elem.showDesignator )
625  pin->SetNumberTextSize( 0 );
626 
627  if( !elem.showPinName )
628  pin->SetNameTextSize( 0 );
629 
630  wxPoint pinLocation = elem.location; // the location given is not the connection point!
631 
632  switch( elem.orientation )
633  {
635  pin->SetOrientation( DrawPinOrient::PIN_LEFT );
636  pinLocation.x += elem.pinlength;
637  break;
639  pin->SetOrientation( DrawPinOrient::PIN_DOWN );
640  pinLocation.y -= elem.pinlength;
641  break;
643  pin->SetOrientation( DrawPinOrient::PIN_RIGHT );
644  pinLocation.x -= elem.pinlength;
645  break;
647  pin->SetOrientation( DrawPinOrient::PIN_UP );
648  pinLocation.y += elem.pinlength;
649  break;
650  default:
651  m_reporter->Report( _( "Pin has unexpected orientation." ), RPT_SEVERITY_WARNING );
652  break;
653  }
654 
655  // TODO: position can be sometimes off a little bit!
656  pin->SetPosition( GetRelativePosition( pinLocation + m_sheetOffset, symbol ) );
657 
658  // TODO: the following fix is even worse for now?
659  // pin->SetPosition( GetRelativePosition( elem.kicadLocation, symbol ) );
660 
661  switch( elem.electrical )
662  {
664  pin->SetType( ELECTRICAL_PINTYPE::PT_INPUT );
665  break;
667  pin->SetType( ELECTRICAL_PINTYPE::PT_BIDI );
668  break;
671  break;
674  break;
677  break;
680  break;
683  break;
686  break;
688  default:
690  m_reporter->Report( _( "Pin has unexpected electrical type." ), RPT_SEVERITY_WARNING );
691  break;
692  }
693 
695  m_reporter->Report( _( "Pin has unexpected outer edge type." ), RPT_SEVERITY_WARNING );
696 
698  m_reporter->Report( _( "Pin has unexpected inner edge type." ), RPT_SEVERITY_WARNING );
699 
701  {
702  switch( elem.symbolInnerEdge )
703  {
706  break;
707  default:
708  pin->SetShape( GRAPHIC_PINSHAPE::INVERTED );
709  break;
710  }
711  }
713  {
714  switch( elem.symbolInnerEdge )
715  {
717  pin->SetShape( GRAPHIC_PINSHAPE::CLOCK_LOW );
718  break;
719  default:
720  pin->SetShape( GRAPHIC_PINSHAPE::INPUT_LOW );
721  break;
722  }
723  }
725  {
726  pin->SetShape( GRAPHIC_PINSHAPE::OUTPUT_LOW );
727  }
728  else
729  {
730  switch( elem.symbolInnerEdge )
731  {
733  pin->SetShape( GRAPHIC_PINSHAPE::CLOCK );
734  break;
735  default:
736  pin->SetShape( GRAPHIC_PINSHAPE::LINE ); // nothing to do
737  break;
738  }
739  }
740 }
741 
742 
744  ASCH_RECORD_ORIENTATION orientation )
745 {
746  int vjustify, hjustify;
747  double angle = TEXT_ANGLE_HORIZ;
748 
749  switch( justification )
750  {
751  default:
757  break;
762  break;
767  break;
768  }
769 
770  switch( justification )
771  {
772  default:
778  break;
783  break;
788  break;
789  }
790 
791  switch( orientation )
792  {
795  break;
797  vjustify *= -1;
798  hjustify *= -1;
800  break;
803  break;
805  vjustify *= -1;
806  hjustify *= -1;
808  break;
809  }
810 
811  text->SetVertJustify( static_cast<EDA_TEXT_VJUSTIFY_T>( vjustify ) );
812  text->SetHorizJustify( static_cast<EDA_TEXT_HJUSTIFY_T>( hjustify ) );
813  text->SetTextAngle( angle );
814 }
815 
816 
817 void SCH_ALTIUM_PLUGIN::ParseLabel( const std::map<wxString, wxString>& aProperties )
818 {
819  ASCH_LABEL elem( aProperties );
820 
821  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
822  {
823  std::map<wxString, wxString> variableMap = {
824  { wxT( "APPLICATION_BUILDNUMBER" ), wxT( "KICAD_VERSION" ) },
825  { wxT( "SHEETNUMBER" ), wxT( "#" ) },
826  { wxT( "SHEETTOTAL" ), wxT( "##" ) },
827  { wxT( "TITLE" ), wxT( "TITLE" ) }, // 1:1 maps are sort of useless, but it makes it
828  { wxT( "REVISION" ), wxT( "REVISION" ) }, // easier to see that the list is complete
829  { wxT( "DATE" ), wxT( "ISSUE_DATE" ) },
830  { wxT( "CURRENTDATE" ), wxT( "CURRENT_DATE" ) },
831  { wxT( "COMPANYNAME" ), wxT( "COMPANY" ) },
832  { wxT( "DOCUMENTNAME" ), wxT( "FILENAME" ) },
833  { wxT( "PROJECTNAME" ), wxT( "PROJECTNAME" ) },
834  };
835 
836  wxString kicadText = AltiumSpecialStringsToKiCadVariables( elem.text, variableMap );
837  SCH_TEXT* textItem = new SCH_TEXT( elem.location + m_sheetOffset, kicadText );
838 
839  SetTextPositioning( textItem, elem.justification, elem.orientation );
840 
841  size_t fontId = static_cast<int>( elem.fontId );
842 
843  if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
844  {
845  const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
846  textItem->SetItalic( font.italic );
847  textItem->SetBold( font.bold );
848  textItem->SetTextSize( { font.size / 2, font.size / 2 } );
849  }
850 
851  textItem->SetFlags(IS_NEW );
852  m_currentSheet->GetScreen()->Append( textItem );
853  }
854  else
855  {
856  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
857 
858  if( libSymbolIt == m_libSymbols.end() )
859  {
860  // TODO: e.g. can depend on Template (RECORD=39
861  m_reporter->Report( wxString::Format( _( "Label's owner (%d) not found." ),
862  elem.ownerindex ),
864  return;
865  }
866 
867  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
868  LIB_TEXT* textItem = new LIB_TEXT( libSymbolIt->second );
869  libSymbolIt->second->AddDrawItem( textItem );
870 
871  textItem->SetUnit( elem.ownerpartid );
872 
873  textItem->SetPosition( GetRelativePosition( elem.location + m_sheetOffset, symbol ) );
874  textItem->SetText( elem.text );
875  SetTextPositioning( textItem, elem.justification, elem.orientation );
876 
877  size_t fontId = static_cast<int>( elem.fontId );
878 
879  if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
880  {
881  const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
882  textItem->SetItalic( font.italic );
883  textItem->SetBold( font.bold );
884  textItem->SetTextSize( { font.size / 2, font.size / 2 } );
885  }
886  }
887 }
888 
889 
890 void SCH_ALTIUM_PLUGIN::ParseTextFrame( const std::map<wxString, wxString>& aProperties )
891 {
892  ASCH_TEXT_FRAME elem( aProperties );
893 
894  SCH_TEXT* text = new SCH_TEXT( elem.location + m_sheetOffset, elem.text );
895 
896  switch( elem.alignment )
897  {
898  default:
900  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::SPIN::RIGHT );
901  break;
903  // No support for centered text in Eeschema yet...
904  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::SPIN::RIGHT );
905  break;
907  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::SPIN::LEFT );
908  break;
909  }
910 
911  // TODO: set size and word-wrap once KiCad supports wrapped text.
912 
913  // TODO: set border and background color once KiCad supports them.
914 
915  size_t fontId = static_cast<int>( elem.fontId );
916 
917  if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
918  {
919  const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
920  text->SetItalic( font.italic );
921  text->SetBold( font.bold );
922  text->SetTextSize( { font.size / 2, font.size / 2 } );
923  }
924 
925  text->SetFlags( IS_NEW );
927 }
928 
929 
930 void SCH_ALTIUM_PLUGIN::ParseNote( const std::map<wxString, wxString>& aProperties )
931 {
932  ASCH_NOTE elem( aProperties );
933 
934  SCH_TEXT* text = new SCH_TEXT( elem.location + m_sheetOffset, elem.text );
935 
936  switch( elem.alignment )
937  {
938  default:
940  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::SPIN::RIGHT );
941  break;
943  // No support for centered text in Eeschema yet...
944  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::SPIN::RIGHT );
945  break;
947  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::SPIN::LEFT );
948  break;
949  }
950 
951  // TODO: set size and word-wrap once KiCad supports wrapped text.
952 
953  // TODO: set border and background color once KiCad supports them.
954 
955  // TODO: need some sort of property system for storing author....
956 
957  size_t fontId = static_cast<int>( elem.fontId );
958 
959  if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
960  {
961  const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
962  text->SetItalic( font.italic );
963  text->SetBold( font.bold );
964  text->SetTextSize( { font.size / 2, font.size / 2 } );
965  }
966 
967  text->SetFlags( IS_NEW );
969 }
970 
971 
972 void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProperties )
973 {
974  ASCH_BEZIER elem( aProperties );
975 
976  if( elem.points.size() < 2 )
977  {
978  m_reporter->Report( wxString::Format( _( "Bezier has %d control points. At least 2 are "
979  "expected." ),
980  static_cast<int>( elem.points.size() ) ),
982  return;
983  }
984 
985  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
986  {
987  for( size_t i = 0; i + 1 < elem.points.size(); i += 3 )
988  {
989  if( i + 2 == elem.points.size() )
990  {
991  // special case: single line
992  SCH_LINE* line = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
994 
995  line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
996  line->SetLineWidth( elem.lineWidth );
998 
999  line->SetFlags( IS_NEW );
1000  m_currentSheet->GetScreen()->Append( line );
1001  }
1002  else
1003  {
1004  // simulate Bezier using line segments
1005  std::vector<wxPoint> bezierPoints;
1006  std::vector<wxPoint> polyPoints;
1007 
1008  for( size_t j = i; j < elem.points.size() && j < i + 4; j++ )
1009  bezierPoints.push_back( elem.points.at( j ) + m_sheetOffset );
1010 
1011  BEZIER_POLY converter( bezierPoints );
1012  converter.GetPoly( polyPoints );
1013 
1014  for( size_t k = 0; k + 1 < polyPoints.size(); k++ )
1015  {
1016  SCH_LINE* line = new SCH_LINE( polyPoints.at( k ) + m_sheetOffset,
1018 
1019  line->SetEndPoint( polyPoints.at( k + 1 ) + m_sheetOffset );
1020  line->SetLineWidth( elem.lineWidth );
1021 
1022  line->SetFlags( IS_NEW );
1023  m_currentSheet->GetScreen()->Append( line );
1024  }
1025  }
1026  }
1027  }
1028  else
1029  {
1030  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1031 
1032  if( libSymbolIt == m_libSymbols.end() )
1033  {
1034  // TODO: e.g. can depend on Template (RECORD=39
1035  m_reporter->Report( wxString::Format( _( "Bezier's owner (%d) not found." ),
1036  elem.ownerindex ),
1038  return;
1039  }
1040 
1042  return;
1043 
1044  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1045 
1046  for( size_t i = 0; i + 1 < elem.points.size(); i += 3 )
1047  {
1048  if( i + 2 == elem.points.size() )
1049  {
1050  // special case: single line
1051  LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
1052  libSymbolIt->second->AddDrawItem( line );
1053 
1054  line->SetUnit( elem.ownerpartid );
1055 
1056  for( size_t j = i; j < elem.points.size() && j < i + 2; j++ )
1057  {
1058  line->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset,
1059  symbol ) );
1060  }
1061 
1062  line->SetWidth( elem.lineWidth );
1063  }
1064  else if( i + 3 == elem.points.size() )
1065  {
1066  // TODO: special case of a single line with an extra point?
1067  // I haven't a clue what this is all about, but the sample document we have in
1068  // https://gitlab.com/kicad/code/kicad/-/issues/8974 responds best by treating it
1069  // as another single line special case.
1070  LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
1071  libSymbolIt->second->AddDrawItem( line );
1072 
1073  line->SetUnit( elem.ownerpartid );
1074 
1075  for( size_t j = i; j < elem.points.size() && j < i + 2; j++ )
1076  {
1077  line->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset,
1078  symbol ) );
1079  }
1080 
1081  line->SetWidth( elem.lineWidth );
1082  }
1083  else
1084  {
1085  // Bezier always has exactly 4 control points
1086  LIB_SHAPE* bezier = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::BEZIER );
1087  libSymbolIt->second->AddDrawItem( bezier );
1088 
1089  bezier->SetUnit( elem.ownerpartid );
1090 
1091  for( size_t j = i; j < elem.points.size() && j < i + 4; j++ )
1092  {
1093  wxPoint pos = GetRelativePosition( elem.points.at( j ) + m_sheetOffset, symbol );
1094 
1095  switch( j - i )
1096  {
1097  case 0: bezier->SetStart( pos ); break;
1098  case 1: bezier->SetBezierC1( pos ); break;
1099  case 2: bezier->SetBezierC2( pos ); break;
1100  case 3: bezier->SetEnd( pos ); break;
1101  default: break; // Can't get here but silence warnings
1102  }
1103  }
1104 
1105  bezier->SetWidth( elem.lineWidth );
1106  }
1107  }
1108  }
1109 }
1110 
1111 
1112 void SCH_ALTIUM_PLUGIN::ParsePolyline( const std::map<wxString, wxString>& aProperties )
1113 {
1114  ASCH_POLYLINE elem( aProperties );
1115 
1116  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1117  {
1119  switch( elem.linestyle )
1120  {
1121  default:
1122  case ASCH_POLYLINE_LINESTYLE::SOLID: dashType = PLOT_DASH_TYPE::SOLID; break;
1123  case ASCH_POLYLINE_LINESTYLE::DASHED: dashType = PLOT_DASH_TYPE::DASH; break;
1124  case ASCH_POLYLINE_LINESTYLE::DOTTED: dashType = PLOT_DASH_TYPE::DOT; break;
1126  }
1127 
1128  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
1129  {
1130  SCH_LINE* line = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
1132 
1133  line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
1134  line->SetLineWidth( elem.lineWidth );
1135  line->SetLineStyle( dashType );
1136 
1137  line->SetFlags( IS_NEW );
1138  m_currentSheet->GetScreen()->Append( line );
1139  }
1140  }
1141  else
1142  {
1143  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1144 
1145  if( libSymbolIt == m_libSymbols.end() )
1146  {
1147  // TODO: e.g. can depend on Template (RECORD=39
1148  m_reporter->Report( wxString::Format( _( "Polyline's owner (%d) not found." ),
1149  elem.ownerindex ),
1151  return;
1152  }
1153 
1155  return;
1156 
1157  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1158  LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
1159  libSymbolIt->second->AddDrawItem( line );
1160 
1161  line->SetUnit( elem.ownerpartid );
1162 
1163  for( wxPoint& point : elem.points )
1164  line->AddPoint( GetRelativePosition( point + m_sheetOffset, symbol ) );
1165 
1166  line->SetWidth( elem.lineWidth );
1167  }
1168 }
1169 
1170 
1171 void SCH_ALTIUM_PLUGIN::ParsePolygon( const std::map<wxString, wxString>& aProperties )
1172 {
1173  ASCH_POLYGON elem( aProperties );
1174 
1175  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1176  {
1177  // TODO: we cannot fill this polygon, only draw it for now
1178  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
1179  {
1180  SCH_LINE* line = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
1182  line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
1183  line->SetLineWidth( elem.lineWidth );
1185 
1186  line->SetFlags( IS_NEW );
1187  m_currentSheet->GetScreen()->Append( line );
1188  }
1189 
1190  // close polygon
1191  SCH_LINE* line = new SCH_LINE( elem.points.front() + m_sheetOffset,
1193  line->SetEndPoint( elem.points.back() + m_sheetOffset );
1194  line->SetLineWidth( elem.lineWidth );
1196 
1197  line->SetFlags( IS_NEW );
1198  m_currentSheet->GetScreen()->Append( line );
1199  }
1200  else
1201  {
1202  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1203 
1204  if( libSymbolIt == m_libSymbols.end() )
1205  {
1206  // TODO: e.g. can depend on Template (RECORD=39
1207  m_reporter->Report( wxString::Format( _( "Polygon's owner (%d) not found." ),
1208  elem.ownerindex ),
1210  return;
1211  }
1212 
1214  return;
1215 
1216  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1217  LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
1218  libSymbolIt->second->AddDrawItem( line );
1219 
1220  line->SetUnit( elem.ownerpartid );
1221 
1222  for( wxPoint& point : elem.points )
1223  line->AddPoint( GetRelativePosition( point + m_sheetOffset, symbol ) );
1224 
1225  line->AddPoint( GetRelativePosition( elem.points.front() + m_sheetOffset, symbol ) );
1226 
1227  line->SetWidth( elem.lineWidth );
1228 
1229  if( !elem.isSolid )
1230  line->SetFillMode( FILL_T::NO_FILL );
1231  else if( elem.color == elem.areacolor )
1233  else
1235  }
1236 }
1237 
1238 
1239 void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map<wxString, wxString>& aProperties )
1240 {
1241  ASCH_ROUND_RECTANGLE elem( aProperties );
1242 
1243  wxPoint sheetTopRight = elem.topRight + m_sheetOffset;
1244  wxPoint sheetBottomLeft = elem.bottomLeft + m_sheetOffset;
1245 
1246  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1247  {
1248  const wxPoint topLeft = { sheetBottomLeft.x, sheetTopRight.y };
1249  const wxPoint bottomRight = { sheetTopRight.x, sheetBottomLeft.y };
1250 
1251  // TODO: we cannot fill this rectangle, only draw it for now
1252  // TODO: misses rounded edges
1253  SCH_LINE* lineTop = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1254  lineTop->SetEndPoint( topLeft );
1255  lineTop->SetLineWidth( elem.lineWidth );
1256  lineTop->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1257  lineTop->SetFlags( IS_NEW );
1258  m_currentSheet->GetScreen()->Append( lineTop );
1259 
1260  SCH_LINE* lineBottom = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1261  lineBottom->SetEndPoint( bottomRight );
1262  lineBottom->SetLineWidth( elem.lineWidth );
1263  lineBottom->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1264  lineBottom->SetFlags( IS_NEW );
1265  m_currentSheet->GetScreen()->Append( lineBottom );
1266 
1267  SCH_LINE* lineRight = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1268  lineRight->SetEndPoint( bottomRight );
1269  lineRight->SetLineWidth( elem.lineWidth );
1270  lineRight->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1271  lineRight->SetFlags( IS_NEW );
1272  m_currentSheet->GetScreen()->Append( lineRight );
1273 
1274  SCH_LINE* lineLeft = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1275  lineLeft->SetEndPoint( topLeft );
1276  lineLeft->SetLineWidth( elem.lineWidth );
1277  lineLeft->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1278  lineLeft->SetFlags( IS_NEW );
1279  m_currentSheet->GetScreen()->Append( lineLeft );
1280  }
1281  else
1282  {
1283  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1284 
1285  if( libSymbolIt == m_libSymbols.end() )
1286  {
1287  // TODO: e.g. can depend on Template (RECORD=39
1288  m_reporter->Report( wxString::Format( _( "Rounded rectangle's owner (%d) not found." ),
1289  elem.ownerindex ),
1291  return;
1292  }
1293 
1295  return;
1296 
1297  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1298  // TODO: misses rounded edges
1299  LIB_SHAPE* rect = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::RECT );
1300  libSymbolIt->second->AddDrawItem( rect );
1301 
1302  rect->SetUnit( elem.ownerpartid );
1303 
1304  rect->SetPosition( GetRelativePosition( elem.topRight + m_sheetOffset, symbol ) );
1305  rect->SetEnd( GetRelativePosition( elem.bottomLeft + m_sheetOffset, symbol ) );
1306  rect->SetWidth( elem.lineWidth );
1307 
1308  if( !elem.isSolid )
1309  rect->SetFillMode( FILL_T::NO_FILL );
1310  else if( elem.color == elem.areacolor )
1312  else
1314  }
1315 }
1316 
1317 
1318 void SCH_ALTIUM_PLUGIN::ParseArc( const std::map<wxString, wxString>& aProperties )
1319 {
1320  ASCH_ARC elem( aProperties );
1321 
1322  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1323  {
1324  m_reporter->Report( _( "Arcs on schematic not currently supported." ),
1326  }
1327  else
1328  {
1329  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1330 
1331  if( libSymbolIt == m_libSymbols.end() )
1332  {
1333  // TODO: e.g. can depend on Template (RECORD=39
1334  m_reporter->Report( wxString::Format( _( "Arc's owner (%d) not found." ),
1335  elem.ownerindex ),
1337  return;
1338  }
1339 
1341  return;
1342 
1343  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1344 
1345  if( elem.startAngle == 0 && ( elem.endAngle == 0 || elem.endAngle == 360 ) )
1346  {
1347  LIB_SHAPE* circle = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::CIRCLE );
1348  libSymbolIt->second->AddDrawItem( circle );
1349 
1350  circle->SetUnit( elem.ownerpartid );
1351 
1352  circle->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, symbol ) );
1353  circle->SetEnd( circle->GetPosition() + wxPoint( elem.radius, 0 ) );
1354  circle->SetWidth( elem.lineWidth );
1355  }
1356  else
1357  {
1358  LIB_SHAPE* arc = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::ARC );
1359  libSymbolIt->second->AddDrawItem( arc );
1360  arc->SetUnit( elem.ownerpartid );
1361 
1362  arc->SetCenter( GetRelativePosition( elem.center + m_sheetOffset, symbol ) );
1363 
1364  wxPoint arcStart( elem.radius, 0 );
1365  RotatePoint( &arcStart.x, &arcStart.y, -elem.startAngle * 10.0 );
1366  arcStart += arc->GetCenter();
1367  arc->SetStart( arcStart );
1368 
1369  wxPoint arcEnd( elem.radius, 0 );
1370  RotatePoint( &arcEnd.x, &arcEnd.y, -elem.endAngle * 10.0 );
1371  arcEnd += arc->GetCenter();
1372  arc->SetEnd( arcEnd );
1373 
1374  arc->SetWidth( elem.lineWidth );
1375  }
1376  }
1377 }
1378 
1379 
1380 void SCH_ALTIUM_PLUGIN::ParseLine( const std::map<wxString, wxString>& aProperties )
1381 {
1382  ASCH_LINE elem( aProperties );
1383 
1384  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1385  {
1386  // close polygon
1388  line->SetEndPoint( elem.point2 + m_sheetOffset );
1389  line->SetLineWidth( elem.lineWidth );
1390  line->SetLineStyle( PLOT_DASH_TYPE::SOLID ); // TODO?
1391 
1392  line->SetFlags( IS_NEW );
1393  m_currentSheet->GetScreen()->Append( line );
1394  }
1395  else
1396  {
1397  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1398 
1399  if( libSymbolIt == m_libSymbols.end() )
1400  {
1401  // TODO: e.g. can depend on Template (RECORD=39
1402  m_reporter->Report( wxString::Format( _( "Line's owner (%d) not found." ),
1403  elem.ownerindex ),
1405  return;
1406  }
1407 
1409  return;
1410 
1411  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1412  LIB_SHAPE* line = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::POLY );
1413  libSymbolIt->second->AddDrawItem( line );
1414 
1415  line->SetUnit( elem.ownerpartid );
1416 
1417  line->AddPoint( GetRelativePosition( elem.point1 + m_sheetOffset, symbol ) );
1418  line->AddPoint( GetRelativePosition( elem.point2 + m_sheetOffset, symbol ) );
1419 
1420  line->SetWidth( elem.lineWidth );
1421  }
1422 }
1423 
1424 
1425 void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map<wxString, wxString>& aProperties )
1426 {
1427  ASCH_RECTANGLE elem( aProperties );
1428 
1429  wxPoint sheetTopRight = elem.topRight + m_sheetOffset;
1430  wxPoint sheetBottomLeft = elem.bottomLeft + m_sheetOffset;
1431 
1432  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1433  {
1434  const wxPoint topLeft = { sheetBottomLeft.x, sheetTopRight.y };
1435  const wxPoint bottomRight = { sheetTopRight.x, sheetBottomLeft.y };
1436 
1437  // TODO: we cannot fill this rectangle, only draw it for now
1438  SCH_LINE* lineTop = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1439  lineTop->SetEndPoint( topLeft );
1440  lineTop->SetLineWidth( elem.lineWidth );
1441  lineTop->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1442  lineTop->SetFlags( IS_NEW );
1443  m_currentSheet->GetScreen()->Append( lineTop );
1444 
1445  SCH_LINE* lineBottom = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1446  lineBottom->SetEndPoint( bottomRight );
1447  lineBottom->SetLineWidth( elem.lineWidth );
1448  lineBottom->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1449  lineBottom->SetFlags( IS_NEW );
1450  m_currentSheet->GetScreen()->Append( lineBottom );
1451 
1452  SCH_LINE* lineRight = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1453  lineRight->SetEndPoint( bottomRight );
1454  lineRight->SetLineWidth( elem.lineWidth );
1455  lineRight->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1456  lineRight->SetFlags( IS_NEW );
1457  m_currentSheet->GetScreen()->Append( lineRight );
1458 
1459  SCH_LINE* lineLeft = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1460  lineLeft->SetEndPoint( topLeft );
1461  lineLeft->SetLineWidth( elem.lineWidth );
1462  lineLeft->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1463  lineLeft->SetFlags( IS_NEW );
1464  m_currentSheet->GetScreen()->Append( lineLeft );
1465  }
1466  else
1467  {
1468  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1469 
1470  if( libSymbolIt == m_libSymbols.end() )
1471  {
1472  // TODO: e.g. can depend on Template (RECORD=39
1473  m_reporter->Report( wxString::Format( _( "Rectangle's owner (%d) not found." ),
1474  elem.ownerindex ),
1476  return;
1477  }
1478 
1480  return;
1481 
1482  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1483  LIB_SHAPE* rect = new LIB_SHAPE( libSymbolIt->second, SHAPE_T::RECT );
1484  libSymbolIt->second->AddDrawItem( rect );
1485 
1486  rect->SetUnit( elem.ownerpartid );
1487 
1488  rect->SetPosition( GetRelativePosition( sheetTopRight, symbol ) );
1489  rect->SetEnd( GetRelativePosition( sheetBottomLeft, symbol ) );
1490  rect->SetWidth( elem.lineWidth );
1491 
1492  if( !elem.isSolid )
1493  rect->SetFillMode( FILL_T::NO_FILL );
1494  else if( elem.color == elem.areacolor )
1496  else
1498  }
1499 }
1500 
1501 
1503  const std::map<wxString, wxString>& aProperties )
1504 {
1505  ASCH_SHEET_SYMBOL elem( aProperties );
1506 
1507  SCH_SHEET* sheet = new SCH_SHEET( m_currentSheet, elem.location + m_sheetOffset );
1508  SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
1509 
1510  sheet->SetSize( elem.size );
1511  sheet->SetBorderColor( GetColorFromInt( elem.color ) );
1512 
1513  if( elem.isSolid )
1514  sheet->SetBackgroundColor( GetColorFromInt( elem.areacolor ) );
1515 
1516  sheet->SetScreen( screen );
1517 
1518  sheet->SetFlags( IS_NEW );
1519  m_currentSheet->GetScreen()->Append( sheet );
1520 
1521  SCH_SHEET_PATH sheetpath;
1523  sheetpath.push_back( sheet );
1524 
1525  sheet->AddInstance( sheetpath );
1526  sheet->SetPageNumber( sheetpath, wxT( "#" ) ); // We'll update later if we find a pageNumber
1527  // record for it
1528 
1529  m_sheets.insert( { aIndex, sheet } );
1530 }
1531 
1532 
1533 void SCH_ALTIUM_PLUGIN::ParseSheetEntry( const std::map<wxString, wxString>& aProperties )
1534 {
1535  ASCH_SHEET_ENTRY elem( aProperties );
1536 
1537  const auto& sheetIt = m_sheets.find( elem.ownerindex );
1538 
1539  if( sheetIt == m_sheets.end() )
1540  {
1541  m_reporter->Report( wxString::Format( _( "Sheet entry's owner (%d) not found." ),
1542  elem.ownerindex ),
1544  return;
1545  }
1546 
1547  SCH_SHEET_PIN* sheetPin = new SCH_SHEET_PIN( sheetIt->second );
1548  sheetIt->second->AddPin( sheetPin );
1549 
1550  sheetPin->SetText( elem.name );
1552  //sheetPin->SetLabelSpinStyle( getSpinStyle( term.OrientAngle, false ) );
1553  //sheetPin->SetPosition( getKiCadPoint( term.Position ) );
1554 
1555  wxPoint pos = sheetIt->second->GetPosition();
1556  wxSize size = sheetIt->second->GetSize();
1557 
1558  switch( elem.side )
1559  {
1560  default:
1562  sheetPin->SetPosition( { pos.x, pos.y + elem.distanceFromTop } );
1564  sheetPin->SetSide( SHEET_SIDE::LEFT );
1565  break;
1567  sheetPin->SetPosition( { pos.x + size.x, pos.y + elem.distanceFromTop } );
1569  sheetPin->SetSide( SHEET_SIDE::RIGHT );
1570  break;
1572  sheetPin->SetPosition( { pos.x + elem.distanceFromTop, pos.y } );
1574  sheetPin->SetSide( SHEET_SIDE::TOP );
1575  break;
1577  sheetPin->SetPosition( { pos.x + elem.distanceFromTop, pos.y + size.y } );
1579  sheetPin->SetSide( SHEET_SIDE::BOTTOM );
1580  break;
1581  }
1582 
1583  switch( elem.iotype )
1584  {
1585  default:
1588  break;
1591  break;
1594  break;
1597  break;
1598  }
1599 }
1600 
1601 
1603  REPORTER* aReporter )
1604 {
1605  if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE || aStyle == ASCH_POWER_PORT_STYLE::ARROW )
1606  {
1607  LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1608  aKsymbol->AddDrawItem( line1 );
1609  line1->SetWidth( Mils2iu( 10 ) );
1610  line1->AddPoint( { 0, 0 } );
1611  line1->AddPoint( { 0, Mils2iu( -50 ) } );
1612 
1613  if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE )
1614  {
1615  LIB_SHAPE* circle = new LIB_SHAPE( aKsymbol, SHAPE_T::CIRCLE );
1616  aKsymbol->AddDrawItem( circle );
1617  circle->SetWidth( Mils2iu( 5 ) );
1618  circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -75 ) } );
1619  circle->SetEnd( circle->GetPosition() + wxPoint( Mils2iu( 25 ), 0 ) );
1620  }
1621  else
1622  {
1623  LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1624  aKsymbol->AddDrawItem( line2 );
1625  line2->SetWidth( Mils2iu( 10 ) );
1626  line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
1627  line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } );
1628  line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
1629  line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
1630  }
1631 
1632  return { 0, Mils2iu( 150 ) };
1633  }
1634  else if( aStyle == ASCH_POWER_PORT_STYLE::WAVE )
1635  {
1636  LIB_SHAPE* line = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1637  aKsymbol->AddDrawItem( line );
1638  line->SetWidth( Mils2iu( 10 ) );
1639  line->AddPoint( { 0, 0 } );
1640  line->AddPoint( { 0, Mils2iu( -72 ) } );
1641 
1642  LIB_SHAPE* bezier = new LIB_SHAPE( aKsymbol, SHAPE_T::BEZIER );
1643  aKsymbol->AddDrawItem( bezier );
1644  bezier->SetWidth( Mils2iu( 5 ) );
1645  bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -50 ) } );
1646  bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -87 ) } );
1647  bezier->AddPoint( { Mils2iu( -30 ), Mils2iu( -63 ) } );
1648  bezier->AddPoint( { Mils2iu( -30 ), Mils2iu( -100 ) } );
1649 
1650  return { 0, Mils2iu( 150 ) };
1651  }
1652  else if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND
1654  || aStyle == ASCH_POWER_PORT_STYLE::EARTH
1655  || aStyle == ASCH_POWER_PORT_STYLE::GOST_ARROW )
1656  {
1657  LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1658  aKsymbol->AddDrawItem( line1 );
1659  line1->SetWidth( Mils2iu( 10 ) );
1660  line1->AddPoint( { 0, 0 } );
1661  line1->AddPoint( { 0, Mils2iu( -100 ) } );
1662 
1663  if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND )
1664  {
1665  LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1666  aKsymbol->AddDrawItem( line2 );
1667  line2->SetWidth( Mils2iu( 10 ) );
1668  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1669  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
1670 
1671  LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1672  aKsymbol->AddDrawItem( line3 );
1673  line3->SetWidth( Mils2iu( 10 ) );
1674  line3->AddPoint( { Mils2iu( -70 ), Mils2iu( -130 ) } );
1675  line3->AddPoint( { Mils2iu( 70 ), Mils2iu( -130 ) } );
1676 
1677  LIB_SHAPE* line4 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1678  aKsymbol->AddDrawItem( line4 );
1679  line4->SetWidth( Mils2iu( 10 ) );
1680  line4->AddPoint( { Mils2iu( -40 ), Mils2iu( -160 ) } );
1681  line4->AddPoint( { Mils2iu( 40 ), Mils2iu( -160 ) } );
1682 
1683  LIB_SHAPE* line5 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1684  aKsymbol->AddDrawItem( line5 );
1685  line5->SetWidth( Mils2iu( 10 ) );
1686  line5->AddPoint( { Mils2iu( -10 ), Mils2iu( -190 ) } );
1687  line5->AddPoint( { Mils2iu( 10 ), Mils2iu( -190 ) } );
1688  }
1689  else if( aStyle == ASCH_POWER_PORT_STYLE::SIGNAL_GROUND )
1690  {
1691  LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1692  aKsymbol->AddDrawItem( line2 );
1693  line2->SetWidth( Mils2iu( 10 ) );
1694  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1695  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
1696  line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -200 ) } );
1697  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1698  }
1699  else if( aStyle == ASCH_POWER_PORT_STYLE::EARTH )
1700  {
1701  LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1702  aKsymbol->AddDrawItem( line2 );
1703  line2->SetWidth( Mils2iu( 10 ) );
1704  line2->AddPoint( { Mils2iu( -150 ), Mils2iu( -200 ) } );
1705  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1706  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
1707  line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -200 ) } );
1708 
1709  LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1710  aKsymbol->AddDrawItem( line3 );
1711  line3->SetWidth( Mils2iu( 10 ) );
1712  line3->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
1713  line3->AddPoint( { Mils2iu( -50 ), Mils2iu( -200 ) } );
1714  }
1715  else // ASCH_POWER_PORT_STYLE::GOST_ARROW
1716  {
1717  LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1718  aKsymbol->AddDrawItem( line2 );
1719  line2->SetWidth( Mils2iu( 10 ) );
1720  line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
1721  line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
1722  line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } );
1723 
1724  return { 0, Mils2iu( 150 ) }; // special case
1725  }
1726 
1727  return { 0, Mils2iu( 250 ) };
1728  }
1729  else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_POWER_GROUND
1730  || aStyle == ASCH_POWER_PORT_STYLE::GOST_EARTH )
1731  {
1732  LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1733  aKsymbol->AddDrawItem( line1 );
1734  line1->SetWidth( Mils2iu( 10 ) );
1735  line1->AddPoint( { 0, 0 } );
1736  line1->AddPoint( { 0, Mils2iu( -160 ) } );
1737 
1738  LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1739  aKsymbol->AddDrawItem( line2 );
1740  line2->SetWidth( Mils2iu( 10 ) );
1741  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -160 ) } );
1742  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -160 ) } );
1743 
1744  LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1745  aKsymbol->AddDrawItem( line3 );
1746  line3->SetWidth( Mils2iu( 10 ) );
1747  line3->AddPoint( { Mils2iu( -60 ), Mils2iu( -200 ) } );
1748  line3->AddPoint( { Mils2iu( 60 ), Mils2iu( -200 ) } );
1749 
1750  LIB_SHAPE* line4 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1751  aKsymbol->AddDrawItem( line4 );
1752  line4->SetWidth( Mils2iu( 10 ) );
1753  line4->AddPoint( { Mils2iu( -20 ), Mils2iu( -240 ) } );
1754  line4->AddPoint( { Mils2iu( 20 ), Mils2iu( -240 ) } );
1755 
1757  return { 0, Mils2iu( 300 ) };
1758 
1759  LIB_SHAPE* circle = new LIB_SHAPE( aKsymbol, SHAPE_T::CIRCLE );
1760  aKsymbol->AddDrawItem( circle );
1761  circle->SetWidth( Mils2iu( 10 ) );
1762  circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -160 ) } );
1763  circle->SetEnd( circle->GetPosition() + wxPoint( Mils2iu( 120 ), 0 ) );
1764 
1765  return { 0, Mils2iu( 350 ) };
1766  }
1767  else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_BAR )
1768  {
1769  LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1770  aKsymbol->AddDrawItem( line1 );
1771  line1->SetWidth( Mils2iu( 10 ) );
1772  line1->AddPoint( { 0, 0 } );
1773  line1->AddPoint( { 0, Mils2iu( -200 ) } );
1774 
1775  LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1776  aKsymbol->AddDrawItem( line2 );
1777  line2->SetWidth( Mils2iu( 10 ) );
1778  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -200 ) } );
1779  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -200 ) } );
1780 
1781  return { 0, Mils2iu( 250 ) };
1782  }
1783  else
1784  {
1785  if( aStyle != ASCH_POWER_PORT_STYLE::BAR )
1786  {
1787  aReporter->Report( _( "Power Port has unknown style, use bar instead." ),
1789  }
1790 
1791  LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1792  aKsymbol->AddDrawItem( line1 );
1793  line1->SetWidth( Mils2iu( 10 ) );
1794  line1->AddPoint( { 0, 0 } );
1795  line1->AddPoint( { 0, Mils2iu( -100 ) } );
1796 
1797  LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
1798  aKsymbol->AddDrawItem( line2 );
1799  line2->SetWidth( Mils2iu( 10 ) );
1800  line2->AddPoint( { Mils2iu( -50 ), Mils2iu( -100 ) } );
1801  line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -100 ) } );
1802 
1803  return { 0, Mils2iu( 150 ) };
1804  }
1805 }
1806 
1807 
1808 void SCH_ALTIUM_PLUGIN::ParsePowerPort( const std::map<wxString, wxString>& aProperties )
1809 {
1810  ASCH_POWER_PORT elem( aProperties );
1811  LIB_ID libId = AltiumToKiCadLibID( getLibName(), elem.text );
1812  LIB_SYMBOL* libSymbol = nullptr;
1813 
1814  const auto& powerSymbolIt = m_powerSymbols.find( elem.text );
1815 
1816  if( powerSymbolIt != m_powerSymbols.end() )
1817  {
1818  libSymbol = powerSymbolIt->second; // cache hit
1819  }
1820  else
1821  {
1822  libSymbol = new LIB_SYMBOL( wxEmptyString );
1823  libSymbol->SetPower();
1824  libSymbol->SetName( elem.text );
1825  libSymbol->GetReferenceField().SetText( wxT( "#PWR" ) );
1826  libSymbol->GetValueField().SetText( elem.text );
1827  libSymbol->GetValueField().SetVisible( true );
1828  libSymbol->SetDescription( wxString::Format( _( "Power symbol creates a global "
1829  "label with name '%s'" ), elem.text ) );
1830  libSymbol->SetKeyWords( wxT( "power-flag" ) );
1831  libSymbol->SetLibId( libId );
1832 
1833  // generate graphic
1834  LIB_PIN* pin = new LIB_PIN( libSymbol );
1835  libSymbol->AddDrawItem( pin );
1836 
1837  pin->SetName( elem.text );
1838  pin->SetPosition( { 0, 0 } );
1839  pin->SetLength( 0 );
1840 
1841  // marks the pin as a global label
1843  pin->SetVisible( false );
1844 
1845  wxPoint valueFieldPos = HelperGeneratePowerPortGraphics( libSymbol, elem.style, m_reporter );
1846 
1847  libSymbol->GetValueField().SetPosition( valueFieldPos );
1848 
1849  // this has to be done after parsing the LIB_SYMBOL!
1850  m_pi->SaveSymbol( getLibFileName().GetFullPath(), libSymbol, m_properties.get() );
1851  m_powerSymbols.insert( { elem.text, libSymbol } );
1852  }
1853 
1854  SCH_SHEET_PATH sheetpath;
1856 
1857  // each symbol has its own powerSymbolIt for now
1858  SCH_SYMBOL* symbol = new SCH_SYMBOL();
1859  symbol->SetRef( &sheetpath, wxT( "#PWR?" ) );
1860  symbol->SetValue( elem.text );
1861  symbol->SetLibId( libId );
1862  symbol->SetLibSymbol( new LIB_SYMBOL( *libSymbol ) );
1863 
1864  SCH_FIELD* valueField = symbol->GetField( VALUE_FIELD );
1865  valueField->SetVisible( elem.showNetName );
1866 
1867  // TODO: Why do I need to set this a second time?
1868  valueField->SetPosition( libSymbol->GetValueField().GetPosition() );
1869 
1870  symbol->SetPosition( elem.location + m_sheetOffset );
1871 
1872  switch( elem.orientation )
1873  {
1876  valueField->SetTextAngle( TEXT_ANGLE_VERT );
1878  break;
1881  valueField->SetTextAngle( TEXT_ANGLE_HORIZ );
1883  break;
1886  valueField->SetTextAngle( TEXT_ANGLE_VERT );
1888  break;
1891  valueField->SetTextAngle( TEXT_ANGLE_HORIZ );
1893  break;
1894  default:
1895  m_reporter->Report( _( "Pin has unexpected orientation." ), RPT_SEVERITY_WARNING );
1896  break;
1897  }
1898 
1899  m_currentSheet->GetScreen()->Append( symbol );
1900 }
1901 
1902 
1904 {
1905  bool isHarness = !aElem.harnessType.IsEmpty();
1906  wxPoint start = aElem.location + m_sheetOffset;
1907  wxPoint end = start;
1908 
1909  switch( aElem.style )
1910  {
1911  default:
1913  case ASCH_PORT_STYLE::LEFT:
1916  end.x += aElem.width;
1917  break;
1919  case ASCH_PORT_STYLE::TOP:
1922  end.y -= aElem.width;
1923  break;
1924  }
1925 
1926  // Check which connection points exists in the schematic
1927  SCH_SCREEN* screen = m_currentSheet->GetScreen();
1928 
1929  bool startIsWireTerminal = screen->IsTerminalPoint( start, LAYER_WIRE );
1930  bool startIsBusTerminal = screen->IsTerminalPoint( start, LAYER_BUS );
1931 
1932  bool endIsWireTerminal = screen->IsTerminalPoint( end, LAYER_WIRE );
1933  bool endIsBusTerminal = screen->IsTerminalPoint( end, LAYER_BUS );
1934 
1935  // check if any of the points is a terminal point
1936  // TODO: there seems a problem to detect approximated connections towards component pins?
1937  bool connectionFound = startIsWireTerminal
1938  || startIsBusTerminal
1939  || endIsWireTerminal
1940  || endIsBusTerminal;
1941 
1942  if( !isHarness && !connectionFound )
1943  {
1944  m_reporter->Report( wxString::Format( _( "Port %s has no connections." ), aElem.name ),
1946  }
1947 
1948  // Select label position. In case both match, we will add a line later.
1949  wxPoint position = ( startIsWireTerminal || startIsBusTerminal ) ? start : end;
1950  SCH_TEXT* label;
1951 
1952  if( isHarness )
1953  {
1954  wxString name = wxT( "HARNESS: " ) + aElem.name;
1955 
1956  if( aElem.harnessType != aElem.name )
1957  name += wxString::Format( wxT( " (%s)" ), aElem.harnessType );
1958 
1959  label = new SCH_TEXT( position, name );
1960  }
1961  // TODO: detect correct label type depending on sheet settings, etc.
1962  //{
1963  // label = new SCH_HIERLABEL( elem.location + m_sheetOffset, elem.name );
1964  //}
1965  else
1966  {
1967 
1968  label = new SCH_GLOBALLABEL( position, aElem.name );
1969  }
1970 
1971  switch( aElem.iotype )
1972  {
1973  default:
1976  break;
1979  break;
1982  break;
1985  break;
1986  }
1987 
1988  switch( aElem.style )
1989  {
1990  default:
1992  case ASCH_PORT_STYLE::LEFT:
1995  if( ( startIsWireTerminal || startIsBusTerminal ) )
1997  else
1999  break;
2001  case ASCH_PORT_STYLE::TOP:
2004  if( ( startIsWireTerminal || startIsBusTerminal ) )
2006  else
2008  break;
2009  }
2010 
2011  label->SetFlags( IS_NEW );
2012  m_currentSheet->GetScreen()->Append( label );
2013 
2014  // This is a hack, for the case both connection points are valid: add a small wire
2015  if( ( startIsWireTerminal && endIsWireTerminal ) )
2016  {
2017  SCH_LINE* wire = new SCH_LINE( start, SCH_LAYER_ID::LAYER_WIRE );
2018  wire->SetEndPoint( end );
2019  wire->SetLineWidth( Mils2iu( 2 ) );
2020  wire->SetFlags( IS_NEW );
2021  m_currentSheet->GetScreen()->Append( wire );
2022  }
2023  else if( startIsBusTerminal && endIsBusTerminal )
2024  {
2025  SCH_LINE* wire = new SCH_LINE( start, SCH_LAYER_ID::LAYER_BUS );
2026  wire->SetEndPoint( end );
2027  wire->SetLineWidth( Mils2iu( 2 ) );
2028  wire->SetFlags( IS_NEW );
2029  m_currentSheet->GetScreen()->Append( wire );
2030  }
2031 }
2032 
2033 
2034 void SCH_ALTIUM_PLUGIN::ParseNoERC( const std::map<wxString, wxString>& aProperties )
2035 {
2036  ASCH_NO_ERC elem( aProperties );
2037 
2038  if( elem.isActive )
2039  {
2040  SCH_NO_CONNECT* noConnect = new SCH_NO_CONNECT( elem.location + m_sheetOffset );
2041 
2042  noConnect->SetFlags( IS_NEW );
2043  m_currentSheet->GetScreen()->Append( noConnect );
2044  }
2045 }
2046 
2047 
2048 void SCH_ALTIUM_PLUGIN::ParseNetLabel( const std::map<wxString, wxString>& aProperties )
2049 {
2050  ASCH_NET_LABEL elem( aProperties );
2051 
2052  SCH_LABEL* label = new SCH_LABEL( elem.location + m_sheetOffset, elem.text );
2053 
2054  switch( elem.orientation )
2055  {
2058  break;
2061  break;
2064  break;
2067  break;
2068  default:
2069  break;
2070  }
2071 
2072  label->SetFlags( IS_NEW );
2073  m_currentSheet->GetScreen()->Append( label );
2074 }
2075 
2076 
2077 void SCH_ALTIUM_PLUGIN::ParseBus( const std::map<wxString, wxString>& aProperties )
2078 {
2079  ASCH_BUS elem( aProperties );
2080 
2081  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
2082  {
2083  SCH_LINE* bus = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
2085  bus->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
2086  bus->SetLineWidth( elem.lineWidth );
2087 
2088  bus->SetFlags( IS_NEW );
2089  m_currentSheet->GetScreen()->Append( bus );
2090  }
2091 }
2092 
2093 
2094 void SCH_ALTIUM_PLUGIN::ParseWire( const std::map<wxString, wxString>& aProperties )
2095 {
2096  ASCH_WIRE elem( aProperties );
2097 
2098  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
2099  {
2100  SCH_LINE* wire =
2101  new SCH_LINE( elem.points.at( i ) + m_sheetOffset, SCH_LAYER_ID::LAYER_WIRE );
2102  wire->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
2103  wire->SetLineWidth( elem.lineWidth );
2104 
2105  wire->SetFlags( IS_NEW );
2106  m_currentSheet->GetScreen()->Append( wire );
2107  }
2108 }
2109 
2110 
2111 void SCH_ALTIUM_PLUGIN::ParseJunction( const std::map<wxString, wxString>& aProperties )
2112 {
2113  ASCH_JUNCTION elem( aProperties );
2114 
2115  SCH_JUNCTION* junction = new SCH_JUNCTION( elem.location + m_sheetOffset );
2116 
2117  junction->SetFlags( IS_NEW );
2118  m_currentSheet->GetScreen()->Append( junction );
2119 }
2120 
2121 
2122 void SCH_ALTIUM_PLUGIN::ParseImage( const std::map<wxString, wxString>& aProperties )
2123 {
2124  ASCH_IMAGE elem( aProperties );
2125 
2126  wxPoint center = ( elem.location + elem.corner ) / 2 + m_sheetOffset;
2127  std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>( center );
2128 
2129  if( elem.embedimage )
2130  {
2131  const ASCH_STORAGE_FILE* storageFile = GetFileFromStorage( elem.filename );
2132 
2133  if( !storageFile )
2134  {
2135  wxString msg = wxString::Format( _( "Embedded file %s not found in storage." ),
2136  elem.filename );
2138  return;
2139  }
2140 
2141  wxString storagePath = wxFileName::CreateTempFileName( wxT( "kicad_import_" ) );
2142 
2143  // As wxZlibInputStream is not seekable, we need to write a temporary file
2144  wxMemoryInputStream fileStream( storageFile->data.data(), storageFile->data.size() );
2145  wxZlibInputStream zlibInputStream( fileStream );
2146  wxFFileOutputStream outputStream( storagePath );
2147  outputStream.Write( zlibInputStream );
2148  outputStream.Close();
2149 
2150  if( !bitmap->ReadImageFile( storagePath ) )
2151  {
2152  m_reporter->Report( wxString::Format( _( "Error reading image %s." ), storagePath ),
2154  return;
2155  }
2156 
2157  // Remove temporary file
2158  wxRemoveFile( storagePath );
2159  }
2160  else
2161  {
2162  if( !wxFileExists( elem.filename ) )
2163  {
2164  m_reporter->Report( wxString::Format( _( "File not found %s." ), elem.filename ),
2166  return;
2167  }
2168 
2169  if( !bitmap->ReadImageFile( elem.filename ) )
2170  {
2171  m_reporter->Report( wxString::Format( _( "Error reading image %s." ), elem.filename ),
2173  return;
2174  }
2175  }
2176 
2177  // we only support one scale, thus we need to select one in case it does not keep aspect ratio
2178  wxSize currentImageSize = bitmap->GetSize();
2179  wxPoint expectedImageSize = elem.location - elem.corner;
2180  double scaleX = std::abs( static_cast<double>( expectedImageSize.x ) / currentImageSize.x );
2181  double scaleY = std::abs( static_cast<double>( expectedImageSize.y ) / currentImageSize.y );
2182  bitmap->SetImageScale( std::min( scaleX, scaleY ) );
2183 
2184  bitmap->SetFlags( IS_NEW );
2185  m_currentSheet->GetScreen()->Append( bitmap.release() );
2186 }
2187 
2188 
2189 void SCH_ALTIUM_PLUGIN::ParseSheet( const std::map<wxString, wxString>& aProperties )
2190 {
2191  m_altiumSheet = std::make_unique<ASCH_SHEET>( aProperties );
2192 
2193  PAGE_INFO pageInfo;
2194 
2195  bool isPortrait = m_altiumSheet->sheetOrientation == ASCH_SHEET_WORKSPACEORIENTATION::PORTRAIT;
2196 
2197  switch( m_altiumSheet->sheetSize )
2198  {
2199  default:
2200  case ASCH_SHEET_SIZE::A4: pageInfo.SetType( wxT( "A4" ), isPortrait ); break;
2201  case ASCH_SHEET_SIZE::A3: pageInfo.SetType( wxT( "A3" ), isPortrait ); break;
2202  case ASCH_SHEET_SIZE::A2: pageInfo.SetType( wxT( "A2" ), isPortrait ); break;
2203  case ASCH_SHEET_SIZE::A1: pageInfo.SetType( wxT( "A1" ), isPortrait ); break;
2204  case ASCH_SHEET_SIZE::A0: pageInfo.SetType( wxT( "A0" ), isPortrait ); break;
2205  case ASCH_SHEET_SIZE::A: pageInfo.SetType( wxT( "A" ), isPortrait ); break;
2206  case ASCH_SHEET_SIZE::B: pageInfo.SetType( wxT( "B" ), isPortrait ); break;
2207  case ASCH_SHEET_SIZE::C: pageInfo.SetType( wxT( "C" ), isPortrait ); break;
2208  case ASCH_SHEET_SIZE::D: pageInfo.SetType( wxT( "D" ), isPortrait ); break;
2209  case ASCH_SHEET_SIZE::E: pageInfo.SetType( wxT( "E" ), isPortrait ); break;
2210  case ASCH_SHEET_SIZE::LETTER: pageInfo.SetType( wxT( "USLetter" ), isPortrait ); break;
2211  case ASCH_SHEET_SIZE::LEGAL: pageInfo.SetType( wxT( "USLegal" ), isPortrait ); break;
2212  case ASCH_SHEET_SIZE::TABLOID: pageInfo.SetType( wxT( "A3" ), isPortrait ); break;
2213  case ASCH_SHEET_SIZE::ORCAD_A: pageInfo.SetType( wxT( "A" ), isPortrait ); break;
2214  case ASCH_SHEET_SIZE::ORCAD_B: pageInfo.SetType( wxT( "B" ), isPortrait ); break;
2215  case ASCH_SHEET_SIZE::ORCAD_C: pageInfo.SetType( wxT( "C" ), isPortrait ); break;
2216  case ASCH_SHEET_SIZE::ORCAD_D: pageInfo.SetType( wxT( "D" ), isPortrait ); break;
2217  case ASCH_SHEET_SIZE::ORCAD_E: pageInfo.SetType( wxT( "E" ), isPortrait ); break;
2218  }
2219 
2220  m_currentSheet->GetScreen()->SetPageSettings( pageInfo );
2221 
2222  m_sheetOffset = { 0, pageInfo.GetHeightIU() };
2223 }
2224 
2225 
2226 void SCH_ALTIUM_PLUGIN::ParseSheetName( const std::map<wxString, wxString>& aProperties )
2227 {
2228  ASCH_SHEET_NAME elem( aProperties );
2229 
2230  const auto& sheetIt = m_sheets.find( elem.ownerindex );
2231 
2232  if( sheetIt == m_sheets.end() )
2233  {
2234  m_reporter->Report( wxString::Format( _( "Sheetname's owner (%d) not found." ),
2235  elem.ownerindex ),
2237  return;
2238  }
2239 
2240  SCH_FIELD& sheetNameField = sheetIt->second->GetFields()[SHEETNAME];
2241 
2242  sheetNameField.SetPosition( elem.location + m_sheetOffset );
2243  sheetNameField.SetText( elem.text );
2244  sheetNameField.SetVisible( !elem.isHidden );
2246 }
2247 
2248 
2249 void SCH_ALTIUM_PLUGIN::ParseFileName( const std::map<wxString, wxString>& aProperties )
2250 {
2251  ASCH_FILE_NAME elem( aProperties );
2252 
2253  const auto& sheetIt = m_sheets.find( elem.ownerindex );
2254 
2255  if( sheetIt == m_sheets.end() )
2256  {
2257  m_reporter->Report( wxString::Format( _( "Filename's owner (%d) not found." ),
2258  elem.ownerindex ),
2260  return;
2261  }
2262 
2263  SCH_FIELD& filenameField = sheetIt->second->GetFields()[SHEETFILENAME];
2264 
2265  filenameField.SetPosition( elem.location + m_sheetOffset );
2266 
2267  // If last symbols are ".sChDoC", change them to ".kicad_sch"
2268  if( ( elem.text.Right( GetFileExtension().length() + 1 ).Lower() )
2269  == ( wxT( "." ) + GetFileExtension().Lower() ) )
2270  {
2271  elem.text.RemoveLast( GetFileExtension().length() );
2273  }
2274 
2275  filenameField.SetText( elem.text );
2276 
2277  filenameField.SetVisible( !elem.isHidden );
2279 }
2280 
2281 
2282 void SCH_ALTIUM_PLUGIN::ParseDesignator( const std::map<wxString, wxString>& aProperties )
2283 {
2284  ASCH_DESIGNATOR elem( aProperties );
2285 
2286  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
2287 
2288  if( libSymbolIt == m_libSymbols.end() )
2289  {
2290  // TODO: e.g. can depend on Template (RECORD=39
2291  m_reporter->Report( wxString::Format( _( "Designator's owner (%d) not found." ),
2292  elem.ownerindex ),
2294  return;
2295  }
2296 
2297  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
2298  SCH_SHEET_PATH sheetpath;
2300 
2301  symbol->SetRef( &sheetpath, elem.text );
2302 
2303  SCH_FIELD* refField = symbol->GetField( REFERENCE_FIELD );
2304 
2305  refField->SetPosition( elem.location + m_sheetOffset );
2306  refField->SetVisible( true );
2307  SetTextPositioning( refField, elem.justification, elem.orientation );
2308 }
2309 
2310 
2311 void SCH_ALTIUM_PLUGIN::ParseBusEntry( const std::map<wxString, wxString>& aProperties )
2312 {
2313  ASCH_BUS_ENTRY elem( aProperties );
2314 
2315  SCH_BUS_WIRE_ENTRY* busWireEntry = new SCH_BUS_WIRE_ENTRY( elem.location + m_sheetOffset );
2316 
2317  wxPoint vector = elem.corner - elem.location;
2318  busWireEntry->SetSize( { vector.x, vector.y } );
2319 
2320  busWireEntry->SetFlags( IS_NEW );
2321  m_currentSheet->GetScreen()->Append( busWireEntry );
2322 }
2323 
2324 
2325 void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map<wxString, wxString>& aProperties )
2326 {
2327  ASCH_PARAMETER elem( aProperties );
2328 
2329  // TODO: fill in replacements from variant, sheet and project
2330  std::map<wxString, wxString> variableMap = {
2331  { wxT( "COMMENT" ), wxT( "VALUE" ) },
2332  { wxT( "VALUE" ), wxT( "ALTIUM_VALUE" ) },
2333  };
2334 
2335  if( elem.ownerindex <= 0 && elem.ownerpartid == ALTIUM_COMPONENT_NONE )
2336  {
2337  // This is some sheet parameter
2338  if( elem.text == wxT( "*" ) )
2339  return; // indicates parameter not set?
2340 
2341  wxString paramName = elem.name.Upper();
2342 
2343  if( paramName == wxT( "SHEETNUMBER" ) )
2344  {
2345  SCH_SHEET_PATH sheetpath;
2347 
2348  m_rootSheet->SetPageNumber( sheetpath, elem.text );
2349  }
2350  else if( paramName == wxT( "TITLE" ) )
2351  {
2352  m_currentTitleBlock->SetTitle( elem.text );
2353  }
2354  else if( paramName == wxT( "REVISION" ) )
2355  {
2356  m_currentTitleBlock->SetRevision( elem.text );
2357  }
2358  else if( paramName == wxT( "DATE" ) )
2359  {
2360  m_currentTitleBlock->SetDate( elem.text );
2361  }
2362  else if( paramName == wxT( "COMPANYNAME" ) )
2363  {
2364  m_currentTitleBlock->SetCompany( elem.text );
2365  }
2366  else
2367  {
2368  m_schematic->Prj().GetTextVars()[ paramName ] = elem.text;
2369  }
2370  }
2371  else
2372  {
2373  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
2374 
2375  if( libSymbolIt == m_libSymbols.end() )
2376  {
2377  // TODO: e.g. can depend on Template (RECORD=39
2378  return;
2379  }
2380 
2381  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
2382  SCH_FIELD* field = nullptr;
2383 
2384  if( elem.name.Upper() == wxT( "COMMENT" ) )
2385  field = symbol->GetField( VALUE_FIELD );
2386  else
2387  {
2388  int fieldIdx = symbol->GetFieldCount();
2389  wxString fieldName = elem.name.Upper();
2390 
2391  if( fieldName == wxT( "VALUE" ) )
2392  fieldName = wxT( "ALTIUM_VALUE" );
2393 
2394  field = symbol->AddField( SCH_FIELD( wxPoint(), fieldIdx, symbol, fieldName ) );
2395  }
2396 
2397  wxString kicadText = AltiumSpecialStringsToKiCadVariables( elem.text, variableMap );
2398  field->SetText( kicadText );
2399  field->SetPosition( elem.location + m_sheetOffset );
2400  field->SetVisible( !elem.isHidden );
2401  SetTextPositioning( field, elem.justification, elem.orientation );
2402  }
2403 }
2404 
2405 
2407  const std::map<wxString, wxString>& aProperties )
2408 {
2409  ASCH_IMPLEMENTATION_LIST elem( aProperties );
2410 
2411  m_altiumImplementationList.emplace( aIndex, elem.ownerindex );
2412 }
2413 
2414 
2415 void SCH_ALTIUM_PLUGIN::ParseImplementation( const std::map<wxString, wxString>& aProperties )
2416 {
2417  ASCH_IMPLEMENTATION elem( aProperties );
2418 
2419  // Only get footprint, currently assigned only
2420  if( ( elem.type == wxT( "PCBLIB" ) ) && ( elem.isCurrent ) )
2421  {
2422  const auto& implementationOwnerIt = m_altiumImplementationList.find( elem.ownerindex );
2423 
2424  if( implementationOwnerIt == m_altiumImplementationList.end() )
2425  {
2426  m_reporter->Report( wxString::Format( _( "Implementation's owner (%d) not found." ),
2427  elem.ownerindex ),
2429  return;
2430  }
2431 
2432  const auto& libSymbolIt = m_libSymbols.find( implementationOwnerIt->second );
2433 
2434  if( libSymbolIt == m_libSymbols.end() )
2435  {
2436  m_reporter->Report( wxString::Format( _( "Footprint's owner (%d) not found." ),
2437  implementationOwnerIt->second ),
2439  return;
2440  }
2441 
2442  LIB_ID fpLibId = AltiumToKiCadLibID( elem.libname, elem.name );
2443  wxArrayString fpFilters;
2444  fpFilters.Add( fpLibId.Format() );
2445 
2446  libSymbolIt->second->SetFPFilters( fpFilters ); // TODO: not ideal as we overwrite it
2447 
2448  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
2449 
2450  symbol->SetFootprint( fpLibId.Format() );
2451  }
2452 }
Field Reference of part, i.e. "IC21".
void ParsePort(const ASCH_PORT &aElem)
wxPoint location
power input (GND, VCC for ICs). Must be connected to a power output.
#define TEXT_ANGLE_HORIZ
Frequent text rotations, used with {Set,Get}TextAngle(), in 0.1 degrees for now, hoping to migrate to...
Definition: eda_text.h:71
static const wxString & GetSymbolLibTableFileName()
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:49
std::unique_ptr< PROPERTIES > m_properties
void SetModified()
Definition: eda_item.cpp:65
static REPORTER & GetInstance()
Definition: reporter.cpp:175
ASCH_RECORD_ORIENTATION orientation
void SetShape(PINSHEETLABEL_SHAPE aShape)
Definition: sch_text.h:163
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:78
void AddPoint(const wxPoint &aPosition)
Definition: lib_shape.cpp:414
void ParseLabel(const std::map< wxString, wxString > &aProperties)
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_PLUGIN obje...
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
void ParseBezier(const std::map< wxString, wxString > &aProperties)
std::vector< char > data
COLOR4D & FromCSSRGBA(int aRed, int aGreen, int aBlue, double aAlpha=1.0)
Initialize the color from a RGBA value with 0-255 red/green/blue and 0-1 alpha.
Definition: color4d.cpp:558
int distanceFromTop
std::map< int, ASCH_SYMBOL > m_altiumComponents
const wxPoint GetRelativePosition(const wxPoint &aPosition, const SCH_SYMBOL *aSymbol)
std::vector< ASCH_STORAGE_FILE > m_altiumStorage
void SetPosition(const wxPoint &aPosition) override
Definition: sch_symbol.h:646
void ParsePowerPort(const std::map< wxString, wxString > &aProperties)
void SetOrientation(int aOrientation)
Compute the new transform matrix based on aOrientation for the symbol which is applied to the current...
void ParseJunction(const std::map< wxString, wxString > &aProperties)
void SetEnd(const wxPoint &aEnd)
Definition: eda_shape.h:135
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:705
void SetTextPositioning(EDA_TEXT *text, ASCH_LABEL_JUSTIFICATION justification, ASCH_RECORD_ORIENTATION orientation)
void SetUnit(int aUnit)
Change the unit number to aUnit.
Definition: sch_symbol.cpp:354
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
Definition: lib_id.cpp:189
Holds all the data relating to one schematic.
Definition: schematic.h:59
void SetSize(const wxSize &aSize)
Definition: sch_bus_entry.h:76
#define IS_NEW
New item, just created.
wxPoint GetPosition() const override
Definition: lib_field.h:157
void ParseImplementation(const std::map< wxString, wxString > &aProperties)
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
void SetSide(SHEET_SIDE aEdge)
void SetFileName(const wxString &aFilename)
Definition: sch_sheet.h:320
Define a symbol library graphical text item.
Definition: lib_text.h:39
bool IsTerminalPoint(const wxPoint &aPosition, int aLayer) const
Test if aPosition is a connection point on aLayer.
Definition: sch_screen.cpp:545
ASCH_PORT_IOTYPE iotype
void GetPoly(std::vector< wxPoint > &aOutput, int aMinSegLen=0)
Convert a Bezier curve to a polygon.
void SetLineWidth(const int aSize)
Definition: sch_line.cpp:305
void ParseParameter(const std::map< wxString, wxString > &aProperties)
size_t GetRemainingBytes() const
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
SCH_SHEET * Load(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const PROPERTIES *aProperties=nullptr) override
Load information from some input file format that this SCH_PLUGIN implementation knows about,...
void ParseRoundRectangle(const std::map< wxString, wxString > &aProperties)
wxString harnessType
std::vector< wxPoint > points
void SetItalic(bool isItalic)
Definition: eda_text.h:200
int color
Definition: DXF_plotter.cpp:57
void SetValue(const SCH_SHEET_PATH *sheet, const wxString &aValue)
Definition: sch_symbol.cpp:624
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:175
pin for passive symbols: must be connected, and can be connected to any pin
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition: schematic.h:108
void ClearEditFlags()
TRANSFORM InverseTransform() const
Calculate the Inverse mirror/rotation transform.
Definition: transform.cpp:57
const wxString GetName() const override
Return a brief hard coded name for this SCH_PLUGIN.
ASCH_LABEL_JUSTIFICATION
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
Definition: page_info.cpp:119
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:152
ASCH_LABEL_JUSTIFICATION justification
int ownerpartdisplaymode
wxString filename
std::map< wxString, LIB_SYMBOL * > m_powerSymbols
void ParseBusEntry(const std::map< wxString, wxString > &aProperties)
unknown electrical properties: creates always a warning when connected
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: sch_screen.h:133
void ParseSheet(const std::map< wxString, wxString > &aProperties)
ASCH_POWER_PORT_STYLE style
void ParsePolygon(const std::map< wxString, wxString > &aProperties)
void set(SCH_PLUGIN *aPlugin)
Definition: sch_io_mgr.h:507
ASCH_PORT_STYLE style
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:258
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:261
Definition: lib_pin.h:48
LIB_FIELD & GetValueField()
Return reference to the value field.
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
wxPoint corner
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:70
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
A name/value tuple with unique names and optional values.
Definition: properties.h:33
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:102
Define a library symbol object.
Definition: lib_symbol.h:96
void SetFootprint(const SCH_SHEET_PATH *sheet, const wxString &aFootprint)
Definition: sch_symbol.cpp:675
TRANSFORM & GetTransform()
Definition: sch_symbol.h:232
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Definition: sch_symbol.cpp:280
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:122
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
void SetPageNumber(const SCH_SHEET_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
Definition: sch_sheet.cpp:1210
void SetBezierC1(const wxPoint &aPt)
Definition: eda_shape.h:153
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:42
std::map< int, SCH_SHEET * > m_sheets
COLOR4D GetColorFromInt(int color)
void SetEndPoint(const wxPoint &aPosition)
Definition: sch_line.h:94
void ParseRectangle(const std::map< wxString, wxString > &aProperties)
void ParsePolyline(const std::map< wxString, wxString > &aProperties)
virtual void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:258
ASCH_RECORD_ORIENTATION orientation
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:140
void SetStart(const wxPoint &aStart)
Definition: eda_shape.h:110
void SetPosition(const wxPoint &aPosition) override
Definition: lib_shape.h:88
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
Definition: schematic.cpp:104
const CFB::COMPOUND_FILE_ENTRY * FindStream(const CFB::CompoundFileReader &aReader, const char *aStreamName)
void ParseImage(const std::map< wxString, wxString > &aProperties)
std::vector< ASCH_PORT > m_altiumPortsCurrentSheet
wxPoint location
virtual void SetVisible(bool aVisible)
Definition: eda_text.h:206
ASCH_RECORD_ORIENTATION orientation
void SetLineStyle(const PLOT_DASH_TYPE aStyle)
Definition: sch_line.cpp:269
ASCH_RECORD_ORIENTATION orientation
wxString libreference
static int ReadInt(const std::map< wxString, wxString > &aProps, const wxString &aKey, int aDefault)
std::map< wxString, wxString > ReadProperties()
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
int ownerindex
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
Definition: sch_symbol.cpp:751
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:114
Field Value of part, i.e. "3.3K".
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:124
void ParseLine(const std::map< wxString, wxString > &aProperties)
ASCH_RECORD_ORIENTATION
std::map< int, SCH_SYMBOL * > m_symbols
wxFileName getLibFileName()
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:53
virtual void SetName(const wxString &aName)
Definition: lib_symbol.cpp:362
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:425
std::unique_ptr< ASCH_SHEET > m_altiumSheet
void ParseSheetEntry(const std::map< wxString, wxString > &aProperties)
std::vector< wxPoint > points
void SetDescription(const wxString &aDescription)
Definition: lib_symbol.h:140
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:111
Definition of file extensions used in Kicad.
void SetLabelSpinStyle(LABEL_SPIN_STYLE aSpinStyle) override
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_text.cpp:1564
#define _(s)
int GetModifyHash() const override
Return the modification hash from the library cache.
void SetWidth(int aWidth)
Definition: eda_shape.h:97
void AddDrawItem(LIB_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
Definition: lib_symbol.cpp:716
std::map< int, LIB_SYMBOL * > m_libSymbols
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet_pin.h:65
int ownerpartdisplaymode
ASCH_RECORD_ORIENTATION orientation
void ParseFileName(const std::map< wxString, wxString > &aProperties)
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
virtual void Format(OUTPUTFORMATTER *aOutput, int aIndentLevel) const override
Generate the table in s-expression format to aOutput with an indentation level of aIndentLevel.
void SetLibId(const LIB_ID &aLibId)
Definition: lib_symbol.h:136
wxPoint GetCenter() const
Definition: lib_shape.h:90
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:314
void SetCenter(const wxPoint &aCenter)
Definition: eda_shape.cpp:419
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: sch_screen.h:158
void ParseNoERC(const std::map< wxString, wxString > &aProperties)
wxString name
UTF8 Format() const
Definition: lib_id.cpp:116
const ASCH_STORAGE_FILE * GetFileFromStorage(const wxString &aFilename) const
std::vector< wxPoint > points
ASCH_RECORD_ORIENTATION orientation
SCH_SHEET * m_currentSheet
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
void SetSize(const wxSize &aSize)
Definition: sch_sheet.h:105
wxPoint HelperGeneratePowerPortGraphics(LIB_SYMBOL *aKsymbol, ASCH_POWER_PORT_STYLE aStyle, REPORTER *aReporter)
PLOT_DASH_TYPE
Dashed line types.
Definition: plotter.h:104
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:75
wxString designator
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
ASCH_PORT_IOTYPE iotype
const wxString GetLibraryFileExtension() const override
Return the library file extension for the SCH_PLUGIN object.
void SetPosition(const wxPoint &aPosition) override
void SetUnit(int aUnit)
Definition: lib_item.h:265
bool LocatePathOfScreen(SCH_SCREEN *aScreen, SCH_SHEET_PATH *aList)
Search the existing hierarchy for an instance of screen loaded from aFileName.
Definition: sch_sheet.cpp:729
LIB_ID AltiumToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
void ParseComponent(int aIndex, const std::map< wxString, wxString > &aProperties)
Bezier curves to polygon converter.
Definition: bezier_curves.h:36
SCH_SHEET & Root() const
Definition: schematic.h:92
void ParseFileHeader(const CFB::CompoundFileReader &aReader)
void ParseSheetSymbol(int aIndex, const std::map< wxString, wxString > &aProperties)
Schematic symbol object.
Definition: sch_symbol.h:78
const char * name
Definition: DXF_plotter.cpp:56
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:146
void ParseNote(const std::map< wxString, wxString > &aProperties)
ASCH_SHEET_ENTRY_SIDE side
ASCH_RECORD_ORIENTATION orientation
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:222
double startAngle
ASCH_PIN_SYMBOL_OUTEREDGE symbolOuterEdge
usual pin input: must be connected
void ParseWire(const std::map< wxString, wxString > &aProperties)
void ParseSheetName(const std::map< wxString, wxString > &aProperties)
void SetPower()
Definition: lib_symbol.cpp:468
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
Definition: sch_symbol.cpp:504
const wxString GetFileExtension() const override
Return the file extension for the SCH_PLUGIN.
const std::string KiCadSchematicFileExtension
wxString AltiumSpecialStringsToKiCadVariables(const wxString &aString, const std::map< wxString, wxString > &aOverrides)
void ParseArc(const std::map< wxString, wxString > &aProperties)
wxPoint GetPosition() const override
Definition: sch_symbol.h:645
void ParseTextFrame(const std::map< wxString, wxString > &aProperties)
void SetBezierC2(const wxPoint &aPt)
Definition: eda_shape.h:156
ASCH_TEXT_FRAME_ALIGNMENT alignment
Used for text file output.
Definition: richio.h:456
ASCH_POLYLINE_LINESTYLE linestyle
void ParseBus(const std::map< wxString, wxString > &aProperties)
Class for a wire to bus entry.
void SetPosition(const wxPoint &aPosition) override
Definition: lib_item.h:230
ASCH_RECORD_ORIENTATION orientation
wxPoint location
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:128
input or output (like port for a microprocessor)
void SetFillMode(FILL_T aFill)
Definition: eda_shape.h:87
void ParseImplementationList(int aIndex, const std::map< wxString, wxString > &aProperties)
const int ALTIUM_COMPONENT_NONE
std::vector< wxPoint > points
void ParseAltiumSch(const wxString &aFileName)
ASCH_POWER_PORT_STYLE
static wxString ReadString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
#define TEXT_ANGLE_VERT
Definition: eda_text.h:72
virtual void SetTextAngle(double aAngle)
Definition: eda_text.h:188
int ownerpartdisplaymode
void ParseDesignator(const std::map< wxString, wxString > &aProperties)
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:110
virtual void SetLabelSpinStyle(LABEL_SPIN_STYLE aSpinStyle)
Set a spin or rotation angle, along with specific horizontal and vertical justification styles with e...
Definition: sch_text.cpp:330
ASCH_PIN_ELECTRICAL electrical
bool CheckHeader(const wxString &aFileName) override
Return true if the first line in aFileName begins with the expected header.
void ParsePin(const std::map< wxString, wxString > &aProperties)
wxPoint GetPosition() const override
Definition: lib_shape.h:87
wxPoint center
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
std::map< int, int > m_altiumImplementationList
SCH_PLUGIN::SCH_PLUGIN_RELEASER m_pi
void ParseStorage(const CFB::CompoundFileReader &aReader)
void SetBold(bool aBold)
Definition: eda_text.h:203
ASCH_PIN_SYMBOL_INNEREDGE symbolInnerEdge
void ParseNetLabel(const std::map< wxString, wxString > &aProperties)
void SetPosition(const wxPoint &aPosition) override
Definition: sch_field.cpp:822
ALTIUM_SCH_RECORD
ASCH_LABEL_JUSTIFICATION justification
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
bool HasParsingError()
bool IsComponentPartVisible(int aOwnerindex, int aOwnerpartdisplaymode) const
wxString componentdescription
void SetKeyWords(const wxString &aKeyWords)
Definition: lib_symbol.h:153
std::unique_ptr< TITLE_BLOCK > m_currentTitleBlock
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:593
ASCH_LABEL_JUSTIFICATION justification
bool AddInstance(const SCH_SHEET_PATH &aInstance)
Add a new instance aSheetPath to the instance list.
Definition: sch_sheet.cpp:1165
std::vector< wxPoint > points
const std::string KiCadSymbolLibFileExtension
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
wxString name