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 <thomas.pointhuber@gmx.at>
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_arc.h>
35 #include <lib_bezier.h>
36 #include <lib_circle.h>
37 #include <lib_id.h>
38 #include <lib_item.h>
39 #include <lib_pin.h>
40 #include <lib_polyline.h>
41 #include <lib_rectangle.h>
42 #include <lib_text.h>
43 
44 #include <sch_bitmap.h>
45 #include <sch_bus_entry.h>
46 #include <sch_symbol.h>
47 #include <sch_junction.h>
48 #include <sch_line.h>
49 #include <sch_no_connect.h>
50 #include <sch_screen.h>
51 #include <sch_sheet.h>
52 #include <sch_sheet_pin.h>
53 #include <sch_text.h>
54 
55 #include <bezier_curves.h>
56 #include <compoundfilereader.h>
57 #include <string_utils.h>
58 #include <sch_edit_frame.h>
59 #include <trigo.h>
61 #include <wx/mstream.h>
62 #include <wx/log.h>
63 #include <wx/zstream.h>
64 #include <wx/wfstream.h>
65 
66 
67 const wxPoint GetRelativePosition( const wxPoint& aPosition, const SCH_SYMBOL* aSymbol )
68 {
69  TRANSFORM t = aSymbol->GetTransform().InverseTransform();
70  return t.TransformCoordinate( aPosition - aSymbol->GetPosition() );
71 }
72 
73 
75 {
76  int red = color & 0x0000FF;
77  int green = ( color & 0x00FF00 ) >> 8;
78  int blue = ( color & 0xFF0000 ) >> 16;
79 
80  return COLOR4D().FromCSSRGBA( red, green, blue, 1.0 );
81 }
82 
84 {
85  m_rootSheet = nullptr;
86  m_currentSheet = nullptr;
87  m_schematic = nullptr;
88 
90 }
91 
92 
94 {
95 }
96 
97 
98 const wxString SCH_ALTIUM_PLUGIN::GetName() const
99 {
100  return "Altium";
101 }
102 
103 
105 {
106  return "SchDoc";
107 }
108 
109 
111 {
112  return "SchLib";
113 }
114 
115 
117 {
118  return 0;
119 }
120 
121 
122 bool SCH_ALTIUM_PLUGIN::CheckHeader( const wxString& aFileName )
123 {
124  // TODO
125 
126  return true;
127 }
128 
129 
131 {
132  if( m_libName.IsEmpty() )
133  {
134  // Try to come up with a meaningful name
136 
137  if( m_libName.IsEmpty() )
138  {
139  wxFileName fn( m_rootSheet->GetFileName() );
140  m_libName = fn.GetName();
141  }
142 
143  if( m_libName.IsEmpty() )
144  m_libName = "noname";
145 
146  m_libName += "-altium-import";
148  }
149 
150  return m_libName;
151 }
152 
153 
155 {
157 
158  return fn;
159 }
160 
161 
162 SCH_SHEET* SCH_ALTIUM_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchematic,
163  SCH_SHEET* aAppendToMe, const PROPERTIES* aProperties )
164 {
165  wxASSERT( !aFileName || aSchematic != nullptr );
166 
167  wxFileName fileName( aFileName );
168  fileName.SetExt( KiCadSchematicFileExtension );
169  m_schematic = aSchematic;
170 
171  // Delete on exception, if I own m_rootSheet, according to aAppendToMe
172  std::unique_ptr<SCH_SHEET> deleter( aAppendToMe ? nullptr : m_rootSheet );
173 
174  if( aAppendToMe )
175  {
176  wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
177  m_rootSheet = &aSchematic->Root();
178  }
179  else
180  {
181  m_rootSheet = new SCH_SHEET( aSchematic );
182  m_rootSheet->SetFileName( fileName.GetFullPath() );
183 
184  SCH_SHEET_PATH sheetpath;
185  sheetpath.push_back( m_rootSheet );
186 
187  m_rootSheet->AddInstance( sheetpath.Path() );
188  m_rootSheet->SetPageNumber( sheetpath, "#" ); // We'll update later if we find a
189  // pageNumber record for it
190  }
191 
192  if( !m_rootSheet->GetScreen() )
193  {
194  SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
195  screen->SetFileName( aFileName );
196  m_rootSheet->SetScreen( screen );
197  }
198 
199  SYMBOL_LIB_TABLE* libTable = m_schematic->Prj().SchSymbolLibTable();
200 
201  wxCHECK_MSG( libTable, nullptr, "Could not load symbol lib table." );
202 
203  m_pi.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
204 
207  if( !libTable->HasLibrary( getLibName() ) )
208  {
209  // Create a new empty symbol library.
210  m_pi->CreateSymbolLib( getLibFileName().GetFullPath() );
211  wxString libTableUri = "${KIPRJMOD}/" + getLibFileName().GetFullName();
212 
213  // Add the new library to the project symbol library table.
214  libTable->InsertRow( new SYMBOL_LIB_TABLE_ROW( getLibName(), libTableUri,
215  wxString( "KiCad" ) ) );
216 
217  // Save project symbol library table.
218  wxFileName fn( m_schematic->Prj().GetProjectPath(),
220 
221  // So output formatter goes out of scope and closes the file before reloading.
222  {
223  FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() );
224  libTable->Format( &formatter, 0 );
225  }
226 
227  // Reload the symbol library table.
229  m_schematic->Prj().SchSymbolLibTable();
230  }
231 
233  ParseAltiumSch( aFileName );
234 
235  m_pi->SaveLibrary( getLibFileName().GetFullPath() );
236 
237  SCH_SCREENS allSheets( m_rootSheet );
238  allSheets.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
239  allSheets.ClearEditFlags();
240 
241  return m_rootSheet;
242 }
243 
244 
245 void SCH_ALTIUM_PLUGIN::ParseAltiumSch( const wxString& aFileName )
246 {
247  // Open file
248  FILE* fp = wxFopen( aFileName, "rb" );
249 
250  if( fp == nullptr )
251  {
252  m_reporter->Report( wxString::Format( _( "Cannot open file '%s'." ), aFileName ),
254  return;
255  }
256 
257  fseek( fp, 0, SEEK_END );
258  long len = ftell( fp );
259 
260  if( len < 0 )
261  {
262  fclose( fp );
263  THROW_IO_ERROR( "Read error, cannot determine length of file." );
264  }
265 
266  std::unique_ptr<unsigned char[]> buffer( new unsigned char[len] );
267  fseek( fp, 0, SEEK_SET );
268 
269  size_t bytesRead = fread( buffer.get(), sizeof( unsigned char ), len, fp );
270  fclose( fp );
271 
272  if( static_cast<size_t>( len ) != bytesRead )
273  THROW_IO_ERROR( "Read error." );
274 
275  try
276  {
277  CFB::CompoundFileReader reader( buffer.get(), bytesRead );
278  ParseStorage( reader ); // we need this before parsing the FileHeader
279  ParseFileHeader( reader );
280  }
281  catch( CFB::CFBException& exception )
282  {
283  THROW_IO_ERROR( exception.what() );
284  }
285 }
286 
287 
288 void SCH_ALTIUM_PLUGIN::ParseStorage( const CFB::CompoundFileReader& aReader )
289 {
290  const CFB::COMPOUND_FILE_ENTRY* file = FindStream( aReader, "Storage" );
291 
292  if( file == nullptr )
293  return;
294 
295  ALTIUM_PARSER reader( aReader, file );
296 
297  std::map<wxString, wxString> properties = reader.ReadProperties();
298  wxString header = ALTIUM_PARSER::ReadString( properties, "HEADER", "" );
299  int weight = ALTIUM_PARSER::ReadInt( properties, "WEIGHT", 0 );
300 
301  if( weight < 0 )
302  THROW_IO_ERROR( "Storage weight is negative!" );
303 
304  for( int i = 0; i < weight; i++ )
305  {
306  m_altiumStorage.emplace_back( reader );
307  }
308 
309  if( reader.HasParsingError() )
310  THROW_IO_ERROR( "stream was not parsed correctly!" );
311 
312  // TODO pointhi: is it possible to have multiple headers in one Storage file? Otherwise
313  // throw IO Error.
314  if( reader.GetRemainingBytes() != 0 )
315  {
316  m_reporter->Report( wxString::Format( _( "Storage file not fully parsed "
317  "(%d bytes remaining)." ),
318  reader.GetRemainingBytes() ),
320  }
321 }
322 
323 
324 void SCH_ALTIUM_PLUGIN::ParseFileHeader( const CFB::CompoundFileReader& aReader )
325 {
326  const CFB::COMPOUND_FILE_ENTRY* file = FindStream( aReader, "FileHeader" );
327 
328  if( file == nullptr )
329  THROW_IO_ERROR( "FileHeader not found" );
330 
331  ALTIUM_PARSER reader( aReader, file );
332 
333  if( reader.GetRemainingBytes() <= 0 )
334  {
335  THROW_IO_ERROR( "FileHeader does not contain any data" );
336  }
337  else
338  {
339  std::map<wxString, wxString> properties = reader.ReadProperties();
340 
341  int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", 0 );
342  ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
343 
344  if( record != ALTIUM_SCH_RECORD::HEADER )
345  THROW_IO_ERROR( "Header expected" );
346  }
347 
348  // Prepare some local variables
349  wxASSERT( m_altiumPortsCurrentSheet.empty() );
350  wxASSERT( !m_currentTitleBlock );
351 
352  m_currentTitleBlock = std::make_unique<TITLE_BLOCK>();
353 
354  // index is required to resolve OWNERINDEX
355  for( int index = 0; reader.GetRemainingBytes() > 0; index++ )
356  {
357  std::map<wxString, wxString> properties = reader.ReadProperties();
358 
359  int recordId = ALTIUM_PARSER::ReadInt( properties, "RECORD", 0 );
360  ALTIUM_SCH_RECORD record = static_cast<ALTIUM_SCH_RECORD>( recordId );
361 
362  // see: https://github.com/vadmium/python-altium/blob/master/format.md
363  switch( record )
364  {
366  THROW_IO_ERROR( "Header already parsed" );
368  ParseComponent( index, properties );
369  break;
371  ParsePin( properties );
372  break;
374  break;
376  ParseLabel( properties );
377  break;
379  ParseBezier( properties );
380  break;
382  ParsePolyline( properties );
383  break;
385  ParsePolygon( properties );
386  break;
388  break;
390  break;
392  ParseRoundRectangle( properties );
393  break;
395  break;
397  ParseArc( properties );
398  break;
400  ParseLine( properties );
401  break;
403  ParseRectangle( properties );
404  break;
406  ParseSheetSymbol( index, properties );
407  break;
409  ParseSheetEntry( properties );
410  break;
412  ParsePowerPort( properties );
413  break;
415  // Ports are parsed after the sheet was parsed
416  // This is required because we need all electrical connection points before placing.
417  m_altiumPortsCurrentSheet.emplace_back( properties );
418  break;
420  ParseNoERC( properties );
421  break;
423  ParseNetLabel( properties );
424  break;
426  ParseBus( properties );
427  break;
429  ParseWire( properties );
430  break;
432  ParseTextFrame( properties );
433  break;
435  ParseJunction( properties );
436  break;
438  ParseImage( properties );
439  break;
441  ParseSheet( properties );
442  break;
444  ParseSheetName( properties );
445  break;
447  ParseFileName( properties );
448  break;
450  ParseDesignator( properties );
451  break;
453  ParseBusEntry( properties );
454  break;
456  break;
458  ParseParameter( properties );
459  break;
461  break;
463  ParseImplementationList( index, properties );
464  break;
466  ParseImplementation( properties );
467  break;
469  break;
471  break;
473  break;
475  ParseNote( properties );
476  break;
478  m_reporter->Report( _( "Compile mask not currently supported." ), RPT_SEVERITY_ERROR );
479  break;
481  break;
483  break;
485  break;
487  break;
489  break;
490  default:
491  m_reporter->Report( wxString::Format( _( "Unknown Record id: %d." ), recordId ),
493  break;
494  }
495  }
496 
497  if( reader.HasParsingError() )
498  THROW_IO_ERROR( "stream was not parsed correctly!" );
499 
500  if( reader.GetRemainingBytes() != 0 )
501  THROW_IO_ERROR( "stream is not fully parsed" );
502 
503  // assign LIB_SYMBOL -> COMPONENT
504  for( std::pair<const int, SCH_SYMBOL*>& symbol : m_symbols )
505  {
506  auto libSymbolIt = m_libSymbols.find( symbol.first );
507 
508  if( libSymbolIt == m_libSymbols.end() )
509  THROW_IO_ERROR( "every symbol should have a symbol attached" );
510 
511  m_pi->SaveSymbol( getLibFileName().GetFullPath(),
512  new LIB_SYMBOL( *( libSymbolIt->second ) ), m_properties.get() );
513 
514  symbol.second->SetLibSymbol( libSymbolIt->second );
515  }
516 
517  // Handle title blocks
519  m_currentTitleBlock.reset();
520 
521  // Handle Ports
522  for( const ASCH_PORT& port : m_altiumPortsCurrentSheet )
523  ParsePort( port );
524 
526 
527  m_symbols.clear();
528  m_libSymbols.clear();
529 
530  // Otherwise we cannot save the imported sheet?
532 }
533 
534 
535 bool SCH_ALTIUM_PLUGIN::IsComponentPartVisible( int aOwnerindex, int aOwnerpartdisplaymode ) const
536 {
537  const auto& component = m_altiumComponents.find( aOwnerindex );
538 
539  if( component == m_altiumComponents.end() )
540  return false;
541 
542  return component->second.displaymode == aOwnerpartdisplaymode;
543 }
544 
545 
546 const ASCH_STORAGE_FILE* SCH_ALTIUM_PLUGIN::GetFileFromStorage( const wxString& aFilename ) const
547 {
548  const ASCH_STORAGE_FILE* nonExactMatch = nullptr;
549 
550  for( const ASCH_STORAGE_FILE& file : m_altiumStorage )
551  {
552  if( file.filename.IsSameAs( aFilename ) )
553  return &file;
554 
555  if( file.filename.EndsWith( aFilename ) )
556  nonExactMatch = &file;
557  }
558 
559  return nonExactMatch;
560 }
561 
562 
564  const std::map<wxString, wxString>& aProperties )
565 {
566  auto pair = m_altiumComponents.insert( { aIndex, ASCH_SYMBOL( aProperties ) } );
567  const ASCH_SYMBOL& elem = pair.first->second;
568 
569  // TODO: this is a hack until we correctly apply all transformations to every element
570  wxString name = wxString::Format( "%d%s_%s",
571  elem.orientation,
572  elem.isMirrored ? "_mirrored" : "",
573  elem.libreference );
575 
576  LIB_SYMBOL* ksymbol = new LIB_SYMBOL( wxEmptyString );
577  ksymbol->SetName( name );
578  ksymbol->SetDescription( elem.componentdescription );
579  ksymbol->SetLibId( libId );
580  m_libSymbols.insert( { aIndex, ksymbol } );
581 
582  // each component has its own symbol for now
583  SCH_SYMBOL* symbol = new SCH_SYMBOL();
584 
585  symbol->SetPosition( elem.location + m_sheetOffset );
586 
587  // TODO: keep it simple for now, and only set position.
588  //component->SetOrientation( elem.orientation );
589  symbol->SetLibId( libId );
590 
591  symbol->SetUnit( elem.currentpartid );
592 
593  m_currentSheet->GetScreen()->Append( symbol );
594 
595  m_symbols.insert( { aIndex, symbol } );
596 }
597 
598 
599 void SCH_ALTIUM_PLUGIN::ParsePin( const std::map<wxString, wxString>& aProperties )
600 {
601  ASCH_PIN elem( aProperties );
602 
603  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
604 
605  if( libSymbolIt == m_libSymbols.end() )
606  {
607  // TODO: e.g. can depend on Template (RECORD=39
608  m_reporter->Report( wxString::Format( _( "Pin's owner (%d) not found." ), elem.ownerindex ),
610  return;
611  }
612 
614  return;
615 
616  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
617  LIB_PIN* pin = new LIB_PIN( libSymbolIt->second );
618  libSymbolIt->second->AddDrawItem( pin );
619 
620  pin->SetUnit( elem.ownerpartid );
621 
622  pin->SetName( elem.name );
623  pin->SetNumber( elem.designator );
624  pin->SetLength( elem.pinlength );
625 
626  if( !elem.showDesignator )
627  pin->SetNumberTextSize( 0 );
628 
629  if( !elem.showPinName )
630  pin->SetNameTextSize( 0 );
631 
632  wxPoint pinLocation = elem.location; // the location given is not the connection point!
633 
634  switch( elem.orientation )
635  {
637  pin->SetOrientation( DrawPinOrient::PIN_LEFT );
638  pinLocation.x += elem.pinlength;
639  break;
641  pin->SetOrientation( DrawPinOrient::PIN_DOWN );
642  pinLocation.y -= elem.pinlength;
643  break;
645  pin->SetOrientation( DrawPinOrient::PIN_RIGHT );
646  pinLocation.x -= elem.pinlength;
647  break;
649  pin->SetOrientation( DrawPinOrient::PIN_UP );
650  pinLocation.y += elem.pinlength;
651  break;
652  default:
653  m_reporter->Report( _( "Pin has unexpected orientation." ), RPT_SEVERITY_WARNING );
654  break;
655  }
656 
657  // TODO: position can be sometimes off a little bit!
658  pin->SetPosition( GetRelativePosition( pinLocation + m_sheetOffset, symbol ) );
659 
660  // TODO: the following fix is even worse for now?
661  // pin->SetPosition( GetRelativePosition( elem.kicadLocation, symbol ) );
662 
663  switch( elem.electrical )
664  {
666  pin->SetType( ELECTRICAL_PINTYPE::PT_INPUT );
667  break;
669  pin->SetType( ELECTRICAL_PINTYPE::PT_BIDI );
670  break;
673  break;
676  break;
679  break;
682  break;
685  break;
688  break;
690  default:
692  m_reporter->Report( _( "Pin has unexpected electrical type." ), RPT_SEVERITY_WARNING );
693  break;
694  }
695 
697  m_reporter->Report( _( "Pin has unexpected outer edge type." ), RPT_SEVERITY_WARNING );
698 
700  m_reporter->Report( _( "Pin has unexpected inner edge type." ), RPT_SEVERITY_WARNING );
701 
703  {
704  switch( elem.symbolInnerEdge )
705  {
708  break;
709  default:
710  pin->SetShape( GRAPHIC_PINSHAPE::INVERTED );
711  break;
712  }
713  }
715  {
716  switch( elem.symbolInnerEdge )
717  {
719  pin->SetShape( GRAPHIC_PINSHAPE::CLOCK_LOW );
720  break;
721  default:
722  pin->SetShape( GRAPHIC_PINSHAPE::INPUT_LOW );
723  break;
724  }
725  }
727  {
728  pin->SetShape( GRAPHIC_PINSHAPE::OUTPUT_LOW );
729  }
730  else
731  {
732  switch( elem.symbolInnerEdge )
733  {
735  pin->SetShape( GRAPHIC_PINSHAPE::CLOCK );
736  break;
737  default:
738  pin->SetShape( GRAPHIC_PINSHAPE::LINE ); // nothing to do
739  break;
740  }
741  }
742 }
743 
744 
746  ASCH_RECORD_ORIENTATION orientation )
747 {
748  int vjustify, hjustify;
749  double angle = TEXT_ANGLE_HORIZ;
750 
751  switch( justification )
752  {
753  default:
759  break;
764  break;
769  break;
770  }
771 
772  switch( justification )
773  {
774  default:
780  break;
785  break;
790  break;
791  }
792 
793  switch( orientation )
794  {
797  break;
799  vjustify *= -1;
800  hjustify *= -1;
802  break;
805  break;
807  vjustify *= -1;
808  hjustify *= -1;
810  break;
811  }
812 
813  text->SetVertJustify( static_cast<EDA_TEXT_VJUSTIFY_T>( vjustify ) );
814  text->SetHorizJustify( static_cast<EDA_TEXT_HJUSTIFY_T>( hjustify ) );
815  text->SetTextAngle( angle );
816 }
817 
818 
819 void SCH_ALTIUM_PLUGIN::ParseLabel( const std::map<wxString, wxString>& aProperties )
820 {
821  ASCH_LABEL elem( aProperties );
822 
823  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
824  {
825  std::map<wxString, wxString> variableMap = {
826  { "APPLICATION_BUILDNUMBER", "KICAD_VERSION" },
827  { "SHEETNUMBER", "#" },
828  { "SHEETTOTAL", "##" },
829  { "TITLE", "TITLE" }, // 1:1 maps are sort of useless, but it makes it
830  { "REVISION", "REVISION" }, // easier to see that the list is complete
831  { "DATE", "ISSUE_DATE" },
832  { "CURRENTDATE", "CURRENT_DATE" },
833  { "COMPANYNAME", "COMPANY" },
834  { "DOCUMENTNAME", "FILENAME" },
835  { "PROJECTNAME", "PROJECTNAME" },
836  };
837 
838  wxString kicadText = AltiumSpecialStringsToKiCadVariables( elem.text, variableMap );
839  SCH_TEXT* textItem = new SCH_TEXT( elem.location + m_sheetOffset, kicadText );
840 
841  SetTextPositioning( textItem, elem.justification, elem.orientation );
842 
843  size_t fontId = static_cast<int>( elem.fontId );
844 
845  if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
846  {
847  const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
848  textItem->SetItalic( font.italic );
849  textItem->SetBold( font.bold );
850  textItem->SetTextSize( { font.size / 2, font.size / 2 } );
851  }
852 
853  textItem->SetFlags(IS_NEW );
854  m_currentSheet->GetScreen()->Append( textItem );
855  }
856  else
857  {
858  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
859 
860  if( libSymbolIt == m_libSymbols.end() )
861  {
862  // TODO: e.g. can depend on Template (RECORD=39
863  m_reporter->Report( wxString::Format( _( "Label's owner (%d) not found." ),
864  elem.ownerindex ),
866  return;
867  }
868 
869  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
870  LIB_TEXT* textItem = new LIB_TEXT( libSymbolIt->second );
871  libSymbolIt->second->AddDrawItem( textItem );
872 
873  textItem->SetUnit( elem.ownerpartid );
874 
875  textItem->SetPosition( GetRelativePosition( elem.location + m_sheetOffset, symbol ) );
876  textItem->SetText( elem.text );
877  SetTextPositioning( textItem, elem.justification, elem.orientation );
878 
879  size_t fontId = static_cast<int>( elem.fontId );
880 
881  if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
882  {
883  const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
884  textItem->SetItalic( font.italic );
885  textItem->SetBold( font.bold );
886  textItem->SetTextSize( { font.size / 2, font.size / 2 } );
887  }
888  }
889 }
890 
891 
892 void SCH_ALTIUM_PLUGIN::ParseTextFrame( const std::map<wxString, wxString>& aProperties )
893 {
894  ASCH_TEXT_FRAME elem( aProperties );
895 
896  SCH_TEXT* text = new SCH_TEXT( elem.location + m_sheetOffset, elem.text );
897 
898  switch( elem.alignment )
899  {
900  default:
902  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::SPIN::RIGHT );
903  break;
905  // No support for centered text in Eeschema yet...
906  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::SPIN::RIGHT );
907  break;
909  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::SPIN::LEFT );
910  break;
911  }
912 
913  // TODO: set size and word-wrap once KiCad supports wrapped text.
914 
915  // TODO: set border and background color once KiCad supports them.
916 
917  size_t fontId = static_cast<int>( elem.fontId );
918 
919  if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
920  {
921  const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
922  text->SetItalic( font.italic );
923  text->SetBold( font.bold );
924  text->SetTextSize( { font.size / 2, font.size / 2 } );
925  }
926 
927  text->SetFlags( IS_NEW );
929 }
930 
931 
932 void SCH_ALTIUM_PLUGIN::ParseNote( const std::map<wxString, wxString>& aProperties )
933 {
934  ASCH_NOTE elem( aProperties );
935 
936  SCH_TEXT* text = new SCH_TEXT( elem.location + m_sheetOffset, elem.text );
937 
938  switch( elem.alignment )
939  {
940  default:
942  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::SPIN::RIGHT );
943  break;
945  // No support for centered text in Eeschema yet...
946  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::SPIN::RIGHT );
947  break;
949  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::SPIN::LEFT );
950  break;
951  }
952 
953  // TODO: set size and word-wrap once KiCad supports wrapped text.
954 
955  // TODO: set border and background color once KiCad supports them.
956 
957  // TODO: need some sort of property system for storing author....
958 
959  size_t fontId = static_cast<int>( elem.fontId );
960 
961  if( m_altiumSheet && fontId > 0 && fontId <= m_altiumSheet->fonts.size() )
962  {
963  const ASCH_SHEET_FONT& font = m_altiumSheet->fonts.at( fontId - 1 );
964  text->SetItalic( font.italic );
965  text->SetBold( font.bold );
966  text->SetTextSize( { font.size / 2, font.size / 2 } );
967  }
968 
969  text->SetFlags( IS_NEW );
971 }
972 
973 
974 void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProperties )
975 {
976  ASCH_BEZIER elem( aProperties );
977 
978  if( elem.points.size() < 2 )
979  {
980  m_reporter->Report( wxString::Format( _( "Bezier has %d control points. At least 2 are "
981  "expected." ),
982  static_cast<int>( elem.points.size() ) ),
984  return;
985  }
986 
987  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
988  {
989  for( size_t i = 0; i + 1 < elem.points.size(); i += 3 )
990  {
991  if( i + 2 == elem.points.size() )
992  {
993  // special case: single line
994  SCH_LINE* line = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
996 
997  line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
998  line->SetLineWidth( elem.lineWidth );
1000 
1001  line->SetFlags( IS_NEW );
1002  m_currentSheet->GetScreen()->Append( line );
1003  }
1004  else
1005  {
1006  // simulate Bezier using line segments
1007  std::vector<wxPoint> bezierPoints;
1008  std::vector<wxPoint> polyPoints;
1009 
1010  for( size_t j = i; j < elem.points.size() && j < i + 4; j++ )
1011  bezierPoints.push_back( elem.points.at( j ) + m_sheetOffset );
1012 
1013  BEZIER_POLY converter( bezierPoints );
1014  converter.GetPoly( polyPoints );
1015 
1016  for( size_t k = 0; k + 1 < polyPoints.size(); k++ )
1017  {
1018  SCH_LINE* line = new SCH_LINE( polyPoints.at( k ) + m_sheetOffset,
1020 
1021  line->SetEndPoint( polyPoints.at( k + 1 ) + m_sheetOffset );
1022  line->SetLineWidth( elem.lineWidth );
1023 
1024  line->SetFlags( IS_NEW );
1025  m_currentSheet->GetScreen()->Append( line );
1026  }
1027  }
1028  }
1029  }
1030  else
1031  {
1032  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1033 
1034  if( libSymbolIt == m_libSymbols.end() )
1035  {
1036  // TODO: e.g. can depend on Template (RECORD=39
1037  m_reporter->Report( wxString::Format( _( "Bezier's owner (%d) not found." ),
1038  elem.ownerindex ),
1040  return;
1041  }
1042 
1044  return;
1045 
1046  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1047 
1048  for( size_t i = 0; i + 1 < elem.points.size(); i += 3 )
1049  {
1050  if( i + 2 == elem.points.size() )
1051  {
1052  // special case: single line
1053  LIB_POLYLINE* line = new LIB_POLYLINE( libSymbolIt->second );
1054  libSymbolIt->second->AddDrawItem( line );
1055 
1056  line->SetUnit( elem.ownerpartid );
1057 
1058  for( size_t j = i; j < elem.points.size() && j < i + 2; j++ )
1059  {
1060  line->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset,
1061  symbol ) );
1062  }
1063 
1064  line->SetWidth( elem.lineWidth );
1065  }
1066  else if( i + 3 == elem.points.size() )
1067  {
1068  // TODO: special case of a single line with an extra point?
1069  // I haven't a clue what this is all about, but the sample document we have in
1070  // https://gitlab.com/kicad/code/kicad/-/issues/8974 responds best by treating it
1071  // as another single line special case.
1072  LIB_POLYLINE* line = new LIB_POLYLINE( libSymbolIt->second );
1073  libSymbolIt->second->AddDrawItem( line );
1074 
1075  line->SetUnit( elem.ownerpartid );
1076 
1077  for( size_t j = i; j < elem.points.size() && j < i + 2; j++ )
1078  {
1079  line->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset,
1080  symbol ) );
1081  }
1082 
1083  line->SetWidth( elem.lineWidth );
1084  }
1085  else
1086  {
1087  // Bezier must have exactly 4 control points
1088  LIB_BEZIER* bezier = new LIB_BEZIER( libSymbolIt->second );
1089  libSymbolIt->second->AddDrawItem( bezier );
1090 
1091  bezier->SetUnit( elem.ownerpartid );
1092 
1093  for( size_t j = i; j < elem.points.size() && j < i + 4; j++ )
1094  {
1095  bezier->AddPoint( GetRelativePosition( elem.points.at( j ) + m_sheetOffset,
1096  symbol ) );
1097  }
1098 
1099  bezier->SetWidth( elem.lineWidth );
1100  }
1101  }
1102  }
1103 }
1104 
1105 
1106 void SCH_ALTIUM_PLUGIN::ParsePolyline( const std::map<wxString, wxString>& aProperties )
1107 {
1108  ASCH_POLYLINE elem( aProperties );
1109 
1110  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1111  {
1113  switch( elem.linestyle )
1114  {
1115  default:
1116  case ASCH_POLYLINE_LINESTYLE::SOLID: dashType = PLOT_DASH_TYPE::SOLID; break;
1117  case ASCH_POLYLINE_LINESTYLE::DASHED: dashType = PLOT_DASH_TYPE::DASH; break;
1118  case ASCH_POLYLINE_LINESTYLE::DOTTED: dashType = PLOT_DASH_TYPE::DOT; break;
1120  }
1121 
1122  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
1123  {
1124  SCH_LINE* line = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
1126 
1127  line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
1128  line->SetLineWidth( elem.lineWidth );
1129  line->SetLineStyle( dashType );
1130 
1131  line->SetFlags( IS_NEW );
1132  m_currentSheet->GetScreen()->Append( line );
1133  }
1134  }
1135  else
1136  {
1137  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1138 
1139  if( libSymbolIt == m_libSymbols.end() )
1140  {
1141  // TODO: e.g. can depend on Template (RECORD=39
1142  m_reporter->Report( wxString::Format( _( "Polyline's owner (%d) not found." ),
1143  elem.ownerindex ),
1145  return;
1146  }
1147 
1149  return;
1150 
1151  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1152  LIB_POLYLINE* line = new LIB_POLYLINE( libSymbolIt->second );
1153  libSymbolIt->second->AddDrawItem( line );
1154 
1155  line->SetUnit( elem.ownerpartid );
1156 
1157  for( wxPoint& point : elem.points )
1158  line->AddPoint( GetRelativePosition( point + m_sheetOffset, symbol ) );
1159 
1160  line->SetWidth( elem.lineWidth );
1161  }
1162 }
1163 
1164 
1165 void SCH_ALTIUM_PLUGIN::ParsePolygon( const std::map<wxString, wxString>& aProperties )
1166 {
1167  ASCH_POLYGON elem( aProperties );
1168 
1169  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1170  {
1171  // TODO: we cannot fill this polygon, only draw it for now
1172  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
1173  {
1174  SCH_LINE* line = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
1176  line->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
1177  line->SetLineWidth( elem.lineWidth );
1179 
1180  line->SetFlags( IS_NEW );
1181  m_currentSheet->GetScreen()->Append( line );
1182  }
1183 
1184  // close polygon
1185  SCH_LINE* line = new SCH_LINE( elem.points.front() + m_sheetOffset,
1187  line->SetEndPoint( elem.points.back() + m_sheetOffset );
1188  line->SetLineWidth( elem.lineWidth );
1190 
1191  line->SetFlags( IS_NEW );
1192  m_currentSheet->GetScreen()->Append( line );
1193  }
1194  else
1195  {
1196  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1197 
1198  if( libSymbolIt == m_libSymbols.end() )
1199  {
1200  // TODO: e.g. can depend on Template (RECORD=39
1201  m_reporter->Report( wxString::Format( _( "Polygon's owner (%d) not found." ),
1202  elem.ownerindex ),
1204  return;
1205  }
1206 
1208  return;
1209 
1210  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1211  LIB_POLYLINE* line = new LIB_POLYLINE( libSymbolIt->second );
1212  libSymbolIt->second->AddDrawItem( line );
1213 
1214  line->SetUnit( elem.ownerpartid );
1215 
1216  for( wxPoint& point : elem.points )
1217  line->AddPoint( GetRelativePosition( point + m_sheetOffset, symbol ) );
1218 
1219  line->AddPoint( GetRelativePosition( elem.points.front() + m_sheetOffset, symbol ) );
1220 
1221  line->SetWidth( elem.lineWidth );
1222 
1223  if( !elem.isSolid )
1225  else if( elem.color == elem.areacolor )
1227  else
1229  }
1230 }
1231 
1232 
1233 void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map<wxString, wxString>& aProperties )
1234 {
1235  ASCH_ROUND_RECTANGLE elem( aProperties );
1236 
1237  wxPoint sheetTopRight = elem.topRight + m_sheetOffset;
1238  wxPoint sheetBottomLeft = elem.bottomLeft + m_sheetOffset;
1239 
1240  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1241  {
1242  const wxPoint topLeft = { sheetBottomLeft.x, sheetTopRight.y };
1243  const wxPoint bottomRight = { sheetTopRight.x, sheetBottomLeft.y };
1244 
1245  // TODO: we cannot fill this rectangle, only draw it for now
1246  // TODO: misses rounded edges
1247  SCH_LINE* lineTop = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1248  lineTop->SetEndPoint( topLeft );
1249  lineTop->SetLineWidth( elem.lineWidth );
1250  lineTop->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1251  lineTop->SetFlags( IS_NEW );
1252  m_currentSheet->GetScreen()->Append( lineTop );
1253 
1254  SCH_LINE* lineBottom = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1255  lineBottom->SetEndPoint( bottomRight );
1256  lineBottom->SetLineWidth( elem.lineWidth );
1257  lineBottom->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1258  lineBottom->SetFlags( IS_NEW );
1259  m_currentSheet->GetScreen()->Append( lineBottom );
1260 
1261  SCH_LINE* lineRight = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1262  lineRight->SetEndPoint( bottomRight );
1263  lineRight->SetLineWidth( elem.lineWidth );
1264  lineRight->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1265  lineRight->SetFlags( IS_NEW );
1266  m_currentSheet->GetScreen()->Append( lineRight );
1267 
1268  SCH_LINE* lineLeft = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1269  lineLeft->SetEndPoint( topLeft );
1270  lineLeft->SetLineWidth( elem.lineWidth );
1271  lineLeft->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1272  lineLeft->SetFlags( IS_NEW );
1273  m_currentSheet->GetScreen()->Append( lineLeft );
1274  }
1275  else
1276  {
1277  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1278 
1279  if( libSymbolIt == m_libSymbols.end() )
1280  {
1281  // TODO: e.g. can depend on Template (RECORD=39
1282  m_reporter->Report( wxString::Format( _( "Rounded rectangle's owner (%d) not found." ),
1283  elem.ownerindex ),
1285  return;
1286  }
1287 
1289  return;
1290 
1291  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1292 
1293  // TODO: misses rounded edges
1294  LIB_RECTANGLE* rect = new LIB_RECTANGLE( libSymbolIt->second );
1295  libSymbolIt->second->AddDrawItem( rect );
1296 
1297  rect->SetUnit( elem.ownerpartid );
1298 
1299  rect->SetPosition( GetRelativePosition( elem.topRight + m_sheetOffset, symbol ) );
1300  rect->SetEnd( GetRelativePosition( elem.bottomLeft + m_sheetOffset, symbol ) );
1301  rect->SetWidth( elem.lineWidth );
1302 
1303  if( !elem.isSolid )
1305  else if( elem.color == elem.areacolor )
1307  else
1309  }
1310 }
1311 
1312 
1313 void SCH_ALTIUM_PLUGIN::ParseArc( const std::map<wxString, wxString>& aProperties )
1314 {
1315  ASCH_ARC elem( aProperties );
1316 
1317  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1318  {
1319  m_reporter->Report( _( "Arcs on schematic not currently supported." ),
1321  }
1322  else
1323  {
1324  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1325 
1326  if( libSymbolIt == m_libSymbols.end() )
1327  {
1328  // TODO: e.g. can depend on Template (RECORD=39
1329  m_reporter->Report( wxString::Format( _( "Arc's owner (%d) not found." ),
1330  elem.ownerindex ),
1332  return;
1333  }
1334 
1336  return;
1337 
1338  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1339 
1340  if( elem.startAngle == 0 && ( elem.endAngle == 0 || elem.endAngle == 360 ) )
1341  {
1342  LIB_CIRCLE* circle = new LIB_CIRCLE( libSymbolIt->second );
1343  libSymbolIt->second->AddDrawItem( circle );
1344 
1345  circle->SetUnit( elem.ownerpartid );
1346 
1347  circle->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, symbol ) );
1348  circle->SetRadius( elem.radius );
1349  circle->SetWidth( elem.lineWidth );
1350  }
1351  else
1352  {
1353  if( fmod( 360.0 + elem.endAngle - elem.startAngle, 360.0 ) > 180.0 )
1354  {
1355  m_reporter->Report( _( "Arcs in symbols cannot exceed 180 degrees." ),
1357  return;
1358  }
1359 
1360  LIB_ARC* arc = new LIB_ARC( libSymbolIt->second );
1361  libSymbolIt->second->AddDrawItem( arc );
1362  arc->SetUnit( elem.ownerpartid );
1363  arc->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, symbol ) );
1364  arc->SetRadius( elem.radius );
1365  arc->SetFirstRadiusAngle( elem.startAngle * 10. );
1366  arc->SetSecondRadiusAngle( elem.endAngle * 10. );
1367  arc->CalcEndPoints();
1368  }
1369  }
1370 }
1371 
1372 
1373 void SCH_ALTIUM_PLUGIN::ParseLine( const std::map<wxString, wxString>& aProperties )
1374 {
1375  ASCH_LINE elem( aProperties );
1376 
1377  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1378  {
1379  // close polygon
1381  line->SetEndPoint( elem.point2 + m_sheetOffset );
1382  line->SetLineWidth( elem.lineWidth );
1383  line->SetLineStyle( PLOT_DASH_TYPE::SOLID ); // TODO?
1384 
1385  line->SetFlags( IS_NEW );
1386  m_currentSheet->GetScreen()->Append( line );
1387  }
1388  else
1389  {
1390  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1391 
1392  if( libSymbolIt == m_libSymbols.end() )
1393  {
1394  // TODO: e.g. can depend on Template (RECORD=39
1395  m_reporter->Report( wxString::Format( _( "Line's owner (%d) not found." ),
1396  elem.ownerindex ),
1398  return;
1399  }
1400 
1402  return;
1403 
1404  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1405  LIB_POLYLINE* line = new LIB_POLYLINE( libSymbolIt->second );
1406  libSymbolIt->second->AddDrawItem( line );
1407 
1408  line->SetUnit( elem.ownerpartid );
1409 
1410  line->AddPoint( GetRelativePosition( elem.point1 + m_sheetOffset, symbol ) );
1411  line->AddPoint( GetRelativePosition( elem.point2 + m_sheetOffset, symbol ) );
1412 
1413  line->SetWidth( elem.lineWidth );
1414  }
1415 }
1416 
1417 
1418 void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map<wxString, wxString>& aProperties )
1419 {
1420  ASCH_RECTANGLE elem( aProperties );
1421 
1422  wxPoint sheetTopRight = elem.topRight + m_sheetOffset;
1423  wxPoint sheetBottomLeft = elem.bottomLeft + m_sheetOffset;
1424 
1425  if( elem.ownerpartid == ALTIUM_COMPONENT_NONE )
1426  {
1427  const wxPoint topLeft = { sheetBottomLeft.x, sheetTopRight.y };
1428  const wxPoint bottomRight = { sheetTopRight.x, sheetBottomLeft.y };
1429 
1430  // TODO: we cannot fill this rectangle, only draw it for now
1431  SCH_LINE* lineTop = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1432  lineTop->SetEndPoint( topLeft );
1433  lineTop->SetLineWidth( elem.lineWidth );
1434  lineTop->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1435  lineTop->SetFlags( IS_NEW );
1436  m_currentSheet->GetScreen()->Append( lineTop );
1437 
1438  SCH_LINE* lineBottom = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1439  lineBottom->SetEndPoint( bottomRight );
1440  lineBottom->SetLineWidth( elem.lineWidth );
1441  lineBottom->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1442  lineBottom->SetFlags( IS_NEW );
1443  m_currentSheet->GetScreen()->Append( lineBottom );
1444 
1445  SCH_LINE* lineRight = new SCH_LINE( sheetTopRight, SCH_LAYER_ID::LAYER_NOTES );
1446  lineRight->SetEndPoint( bottomRight );
1447  lineRight->SetLineWidth( elem.lineWidth );
1448  lineRight->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1449  lineRight->SetFlags( IS_NEW );
1450  m_currentSheet->GetScreen()->Append( lineRight );
1451 
1452  SCH_LINE* lineLeft = new SCH_LINE( sheetBottomLeft, SCH_LAYER_ID::LAYER_NOTES );
1453  lineLeft->SetEndPoint( topLeft );
1454  lineLeft->SetLineWidth( elem.lineWidth );
1455  lineLeft->SetLineStyle( PLOT_DASH_TYPE::SOLID );
1456  lineLeft->SetFlags( IS_NEW );
1457  m_currentSheet->GetScreen()->Append( lineLeft );
1458  }
1459  else
1460  {
1461  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
1462 
1463  if( libSymbolIt == m_libSymbols.end() )
1464  {
1465  // TODO: e.g. can depend on Template (RECORD=39
1466  m_reporter->Report( wxString::Format( _( "Rectangle's owner (%d) not found." ),
1467  elem.ownerindex ),
1469  return;
1470  }
1471 
1473  return;
1474 
1475  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
1476  LIB_RECTANGLE* rect = new LIB_RECTANGLE( libSymbolIt->second );
1477  libSymbolIt->second->AddDrawItem( rect );
1478 
1479  rect->SetUnit( elem.ownerpartid );
1480 
1481  rect->SetPosition( GetRelativePosition( sheetTopRight, symbol ) );
1482  rect->SetEnd( GetRelativePosition( sheetBottomLeft, symbol ) );
1483  rect->SetWidth( elem.lineWidth );
1484 
1485  if( !elem.isSolid )
1487  else if( elem.color == elem.areacolor )
1489  else
1491  }
1492 }
1493 
1494 
1496  const std::map<wxString, wxString>& aProperties )
1497 {
1498  ASCH_SHEET_SYMBOL elem( aProperties );
1499 
1500  SCH_SHEET* sheet = new SCH_SHEET( m_currentSheet, elem.location + m_sheetOffset );
1501  SCH_SCREEN* screen = new SCH_SCREEN( m_schematic );
1502 
1503  sheet->SetSize( elem.size );
1504  sheet->SetBorderColor( GetColorFromInt( elem.color ) );
1505 
1506  if( elem.isSolid )
1507  sheet->SetBackgroundColor( GetColorFromInt( elem.areacolor ) );
1508 
1509  sheet->SetScreen( screen );
1510 
1511  sheet->SetFlags( IS_NEW );
1512  m_currentSheet->GetScreen()->Append( sheet );
1513 
1514  SCH_SHEET_PATH sheetpath;
1516  sheetpath.push_back( sheet );
1517 
1518  sheet->AddInstance( sheetpath.Path() );
1519  sheet->SetPageNumber( sheetpath, "#" ); // We'll update later if we find a pageNumber
1520  // record for it
1521 
1522  m_sheets.insert( { aIndex, sheet } );
1523 }
1524 
1525 
1526 void SCH_ALTIUM_PLUGIN::ParseSheetEntry( const std::map<wxString, wxString>& aProperties )
1527 {
1528  ASCH_SHEET_ENTRY elem( aProperties );
1529 
1530  const auto& sheetIt = m_sheets.find( elem.ownerindex );
1531 
1532  if( sheetIt == m_sheets.end() )
1533  {
1534  m_reporter->Report( wxString::Format( _( "Sheet entry's owner (%d) not found." ),
1535  elem.ownerindex ),
1537  return;
1538  }
1539 
1540  SCH_SHEET_PIN* sheetPin = new SCH_SHEET_PIN( sheetIt->second );
1541  sheetIt->second->AddPin( sheetPin );
1542 
1543  sheetPin->SetText( elem.name );
1545  //sheetPin->SetLabelSpinStyle( getSpinStyle( term.OrientAngle, false ) );
1546  //sheetPin->SetPosition( getKiCadPoint( term.Position ) );
1547 
1548  wxPoint pos = sheetIt->second->GetPosition();
1549  wxSize size = sheetIt->second->GetSize();
1550 
1551  switch( elem.side )
1552  {
1553  default:
1555  sheetPin->SetPosition( { pos.x, pos.y + elem.distanceFromTop } );
1557  sheetPin->SetEdge( SHEET_SIDE::LEFT );
1558  break;
1560  sheetPin->SetPosition( { pos.x + size.x, pos.y + elem.distanceFromTop } );
1562  sheetPin->SetEdge( SHEET_SIDE::RIGHT );
1563  break;
1565  sheetPin->SetPosition( { pos.x + elem.distanceFromTop, pos.y } );
1567  sheetPin->SetEdge( SHEET_SIDE::TOP );
1568  break;
1570  sheetPin->SetPosition( { pos.x + elem.distanceFromTop, pos.y + size.y } );
1572  sheetPin->SetEdge( SHEET_SIDE::BOTTOM );
1573  break;
1574  }
1575 
1576  switch( elem.iotype )
1577  {
1578  default:
1581  break;
1584  break;
1587  break;
1590  break;
1591  }
1592 }
1593 
1594 
1596  REPORTER* aReporter )
1597 {
1598  if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE || aStyle == ASCH_POWER_PORT_STYLE::ARROW )
1599  {
1600  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKsymbol );
1601  aKsymbol->AddDrawItem( line1 );
1602  line1->SetWidth( Mils2iu( 10 ) );
1603  line1->AddPoint( { 0, 0 } );
1604  line1->AddPoint( { 0, Mils2iu( -50 ) } );
1605 
1606  if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE )
1607  {
1608  LIB_CIRCLE* circle = new LIB_CIRCLE( aKsymbol );
1609  aKsymbol->AddDrawItem( circle );
1610  circle->SetWidth( Mils2iu( 5 ) );
1611  circle->SetRadius( Mils2iu( 25 ) );
1612  circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -75 ) } );
1613  }
1614  else
1615  {
1616  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol );
1617  aKsymbol->AddDrawItem( line2 );
1618  line2->SetWidth( Mils2iu( 10 ) );
1619  line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
1620  line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } );
1621  line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
1622  line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
1623  }
1624 
1625  return { 0, Mils2iu( 150 ) };
1626  }
1627  else if( aStyle == ASCH_POWER_PORT_STYLE::WAVE )
1628  {
1629  LIB_POLYLINE* line = new LIB_POLYLINE( aKsymbol );
1630  aKsymbol->AddDrawItem( line );
1631  line->SetWidth( Mils2iu( 10 ) );
1632  line->AddPoint( { 0, 0 } );
1633  line->AddPoint( { 0, Mils2iu( -72 ) } );
1634 
1635  LIB_BEZIER* bezier = new LIB_BEZIER( aKsymbol );
1636  aKsymbol->AddDrawItem( bezier );
1637  bezier->SetWidth( Mils2iu( 5 ) );
1638  bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -50 ) } );
1639  bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -87 ) } );
1640  bezier->AddPoint( { Mils2iu( -30 ), Mils2iu( -63 ) } );
1641  bezier->AddPoint( { Mils2iu( -30 ), Mils2iu( -100 ) } );
1642 
1643  return { 0, Mils2iu( 150 ) };
1644  }
1645  else if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND
1647  || aStyle == ASCH_POWER_PORT_STYLE::EARTH
1648  || aStyle == ASCH_POWER_PORT_STYLE::GOST_ARROW )
1649  {
1650  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKsymbol );
1651  aKsymbol->AddDrawItem( line1 );
1652  line1->SetWidth( Mils2iu( 10 ) );
1653  line1->AddPoint( { 0, 0 } );
1654  line1->AddPoint( { 0, Mils2iu( -100 ) } );
1655 
1656  if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND )
1657  {
1658  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol );
1659  aKsymbol->AddDrawItem( line2 );
1660  line2->SetWidth( Mils2iu( 10 ) );
1661  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1662  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
1663 
1664  LIB_POLYLINE* line3 = new LIB_POLYLINE( aKsymbol );
1665  aKsymbol->AddDrawItem( line3 );
1666  line3->SetWidth( Mils2iu( 10 ) );
1667  line3->AddPoint( { Mils2iu( -70 ), Mils2iu( -130 ) } );
1668  line3->AddPoint( { Mils2iu( 70 ), Mils2iu( -130 ) } );
1669 
1670  LIB_POLYLINE* line4 = new LIB_POLYLINE( aKsymbol );
1671  aKsymbol->AddDrawItem( line4 );
1672  line4->SetWidth( Mils2iu( 10 ) );
1673  line4->AddPoint( { Mils2iu( -40 ), Mils2iu( -160 ) } );
1674  line4->AddPoint( { Mils2iu( 40 ), Mils2iu( -160 ) } );
1675 
1676  LIB_POLYLINE* line5 = new LIB_POLYLINE( aKsymbol );
1677  aKsymbol->AddDrawItem( line5 );
1678  line5->SetWidth( Mils2iu( 10 ) );
1679  line5->AddPoint( { Mils2iu( -10 ), Mils2iu( -190 ) } );
1680  line5->AddPoint( { Mils2iu( 10 ), Mils2iu( -190 ) } );
1681  }
1682  else if( aStyle == ASCH_POWER_PORT_STYLE::SIGNAL_GROUND )
1683  {
1684  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol );
1685  aKsymbol->AddDrawItem( line2 );
1686  line2->SetWidth( Mils2iu( 10 ) );
1687  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1688  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
1689  line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -200 ) } );
1690  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1691  }
1692  else if( aStyle == ASCH_POWER_PORT_STYLE::EARTH )
1693  {
1694  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol );
1695  aKsymbol->AddDrawItem( line2 );
1696  line2->SetWidth( Mils2iu( 10 ) );
1697  line2->AddPoint( { Mils2iu( -150 ), Mils2iu( -200 ) } );
1698  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
1699  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
1700  line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -200 ) } );
1701 
1702  LIB_POLYLINE* line3 = new LIB_POLYLINE( aKsymbol );
1703  aKsymbol->AddDrawItem( line3 );
1704  line3->SetWidth( Mils2iu( 10 ) );
1705  line3->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
1706  line3->AddPoint( { Mils2iu( -50 ), Mils2iu( -200 ) } );
1707  }
1708  else // ASCH_POWER_PORT_STYLE::GOST_ARROW
1709  {
1710  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol );
1711  aKsymbol->AddDrawItem( line2 );
1712  line2->SetWidth( Mils2iu( 10 ) );
1713  line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
1714  line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
1715  line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } );
1716 
1717  return { 0, Mils2iu( 150 ) }; // special case
1718  }
1719 
1720  return { 0, Mils2iu( 250 ) };
1721  }
1722  else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_POWER_GROUND
1723  || aStyle == ASCH_POWER_PORT_STYLE::GOST_EARTH )
1724  {
1725  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKsymbol );
1726  aKsymbol->AddDrawItem( line1 );
1727  line1->SetWidth( Mils2iu( 10 ) );
1728  line1->AddPoint( { 0, 0 } );
1729  line1->AddPoint( { 0, Mils2iu( -160 ) } );
1730 
1731  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol );
1732  aKsymbol->AddDrawItem( line2 );
1733  line2->SetWidth( Mils2iu( 10 ) );
1734  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -160 ) } );
1735  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -160 ) } );
1736 
1737  LIB_POLYLINE* line3 = new LIB_POLYLINE( aKsymbol );
1738  aKsymbol->AddDrawItem( line3 );
1739  line3->SetWidth( Mils2iu( 10 ) );
1740  line3->AddPoint( { Mils2iu( -60 ), Mils2iu( -200 ) } );
1741  line3->AddPoint( { Mils2iu( 60 ), Mils2iu( -200 ) } );
1742 
1743  LIB_POLYLINE* line4 = new LIB_POLYLINE( aKsymbol );
1744  aKsymbol->AddDrawItem( line4 );
1745  line4->SetWidth( Mils2iu( 10 ) );
1746  line4->AddPoint( { Mils2iu( -20 ), Mils2iu( -240 ) } );
1747  line4->AddPoint( { Mils2iu( 20 ), Mils2iu( -240 ) } );
1748 
1750  return { 0, Mils2iu( 300 ) };
1751 
1752  LIB_CIRCLE* circle = new LIB_CIRCLE( aKsymbol );
1753  aKsymbol->AddDrawItem( circle );
1754  circle->SetWidth( Mils2iu( 10 ) );
1755  circle->SetRadius( Mils2iu( 120 ) );
1756  circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -160 ) } );
1757 
1758  return { 0, Mils2iu( 350 ) };
1759  }
1760  else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_BAR )
1761  {
1762  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKsymbol );
1763  aKsymbol->AddDrawItem( line1 );
1764  line1->SetWidth( Mils2iu( 10 ) );
1765  line1->AddPoint( { 0, 0 } );
1766  line1->AddPoint( { 0, Mils2iu( -200 ) } );
1767 
1768  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol );
1769  aKsymbol->AddDrawItem( line2 );
1770  line2->SetWidth( Mils2iu( 10 ) );
1771  line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -200 ) } );
1772  line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -200 ) } );
1773 
1774  return { 0, Mils2iu( 250 ) };
1775  }
1776  else
1777  {
1778  if( aStyle != ASCH_POWER_PORT_STYLE::BAR )
1779  {
1780  aReporter->Report( _( "Power Port has unknown style, use bar instead." ),
1782  }
1783 
1784  LIB_POLYLINE* line1 = new LIB_POLYLINE( aKsymbol );
1785  aKsymbol->AddDrawItem( line1 );
1786  line1->SetWidth( Mils2iu( 10 ) );
1787  line1->AddPoint( { 0, 0 } );
1788  line1->AddPoint( { 0, Mils2iu( -100 ) } );
1789 
1790  LIB_POLYLINE* line2 = new LIB_POLYLINE( aKsymbol );
1791  aKsymbol->AddDrawItem( line2 );
1792  line2->SetWidth( Mils2iu( 10 ) );
1793  line2->AddPoint( { Mils2iu( -50 ), Mils2iu( -100 ) } );
1794  line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -100 ) } );
1795 
1796  return { 0, Mils2iu( 150 ) };
1797  }
1798 }
1799 
1800 
1801 void SCH_ALTIUM_PLUGIN::ParsePowerPort( const std::map<wxString, wxString>& aProperties )
1802 {
1803  ASCH_POWER_PORT elem( aProperties );
1804  LIB_ID libId = AltiumToKiCadLibID( getLibName(), elem.text );
1805  LIB_SYMBOL* libSymbol = nullptr;
1806 
1807  const auto& powerSymbolIt = m_powerSymbols.find( elem.text );
1808 
1809  if( powerSymbolIt != m_powerSymbols.end() )
1810  {
1811  libSymbol = powerSymbolIt->second; // cache hit
1812  }
1813  else
1814  {
1815  libSymbol = new LIB_SYMBOL( wxEmptyString );
1816  libSymbol->SetPower();
1817  libSymbol->SetName( elem.text );
1818  libSymbol->GetReferenceField().SetText( "#PWR" );
1819  libSymbol->GetValueField().SetText( elem.text );
1820  libSymbol->GetValueField().SetVisible( true );
1821  libSymbol->SetDescription( wxString::Format( _( "Power symbol creates a global "
1822  "label with name '%s'" ), elem.text ) );
1823  libSymbol->SetKeyWords( "power-flag" );
1824  libSymbol->SetLibId( libId );
1825 
1826  // generate graphic
1827  LIB_PIN* pin = new LIB_PIN( libSymbol );
1828  libSymbol->AddDrawItem( pin );
1829 
1830  pin->SetName( elem.text );
1831  pin->SetPosition( { 0, 0 } );
1832  pin->SetLength( 0 );
1833 
1834  // marks the pin as a global label
1836  pin->SetVisible( false );
1837 
1838  wxPoint valueFieldPos = HelperGeneratePowerPortGraphics( libSymbol, elem.style,
1839  m_reporter );
1840 
1841  libSymbol->GetValueField().SetPosition( valueFieldPos );
1842 
1843  // this has to be done after parsing the LIB_SYMBOL!
1844  m_pi->SaveSymbol( getLibFileName().GetFullPath(), libSymbol, m_properties.get() );
1845  m_powerSymbols.insert( { elem.text, libSymbol } );
1846  }
1847 
1848  SCH_SHEET_PATH sheetpath;
1850 
1851  // each symbol has its own powerSymbolIt for now
1852  SCH_SYMBOL* symbol = new SCH_SYMBOL();
1853  symbol->SetRef( &sheetpath, "#PWR?" );
1854  symbol->SetValue( elem.text );
1855  symbol->SetLibId( libId );
1856  symbol->SetLibSymbol( new LIB_SYMBOL( *libSymbol ) );
1857 
1858  SCH_FIELD* valueField = symbol->GetField( VALUE_FIELD );
1859  valueField->SetVisible( elem.showNetName );
1860 
1861  // TODO: Why do I need to set this a second time?
1862  valueField->SetPosition( libSymbol->GetValueField().GetPosition() );
1863 
1864  symbol->SetPosition( elem.location + m_sheetOffset );
1865 
1866  switch( elem.orientation )
1867  {
1870  valueField->SetTextAngle( TEXT_ANGLE_VERT );
1872  break;
1875  valueField->SetTextAngle( TEXT_ANGLE_HORIZ );
1877  break;
1880  valueField->SetTextAngle( TEXT_ANGLE_VERT );
1882  break;
1885  valueField->SetTextAngle( TEXT_ANGLE_HORIZ );
1887  break;
1888  default:
1889  m_reporter->Report( _( "Pin has unexpected orientation." ), RPT_SEVERITY_WARNING );
1890  break;
1891  }
1892 
1893  m_currentSheet->GetScreen()->Append( symbol );
1894 }
1895 
1896 
1898 {
1899  bool isHarness = !aElem.harnessType.IsEmpty();
1900  wxPoint start = aElem.location + m_sheetOffset;
1901  wxPoint end = start;
1902 
1903  switch( aElem.style )
1904  {
1905  default:
1907  case ASCH_PORT_STYLE::LEFT:
1910  end.x += aElem.width;
1911  break;
1913  case ASCH_PORT_STYLE::TOP:
1916  end.y -= aElem.width;
1917  break;
1918  }
1919 
1920  // Check which connection points exists in the schematic
1921  SCH_SCREEN* screen = m_currentSheet->GetScreen();
1922 
1923  bool startIsWireTerminal = screen->IsTerminalPoint( start, LAYER_WIRE );
1924  bool startIsBusTerminal = screen->IsTerminalPoint( start, LAYER_BUS );
1925 
1926  bool endIsWireTerminal = screen->IsTerminalPoint( end, LAYER_WIRE );
1927  bool endIsBusTerminal = screen->IsTerminalPoint( end, LAYER_BUS );
1928 
1929  // check if any of the points is a terminal point
1930  // TODO: there seems a problem to detect approximated connections towards component pins?
1931  bool connectionFound = startIsWireTerminal
1932  || startIsBusTerminal
1933  || endIsWireTerminal
1934  || endIsBusTerminal;
1935 
1936  if( !isHarness && !connectionFound )
1937  {
1938  m_reporter->Report( wxString::Format( _( "Port %s has no connections." ), aElem.name ),
1940  }
1941 
1942  // Select label position. In case both match, we will add a line later.
1943  wxPoint position = ( startIsWireTerminal || startIsBusTerminal ) ? start : end;
1944  SCH_TEXT* label;
1945 
1946  if( isHarness )
1947  {
1948  wxString name = wxT( "HARNESS: " ) + aElem.name;
1949 
1950  if( aElem.harnessType != aElem.name )
1951  name += wxString::Format( wxT( " (%s)" ), aElem.harnessType );
1952 
1953  label = new SCH_TEXT( position, name );
1954  }
1955  // TODO: detect correct label type depending on sheet settings, etc.
1956  //{
1957  // label = new SCH_HIERLABEL( elem.location + m_sheetOffset, elem.name );
1958  //}
1959  else
1960  {
1961 
1962  label = new SCH_GLOBALLABEL( position, aElem.name );
1963  }
1964 
1965  switch( aElem.iotype )
1966  {
1967  default:
1970  break;
1973  break;
1976  break;
1979  break;
1980  }
1981 
1982  switch( aElem.style )
1983  {
1984  default:
1986  case ASCH_PORT_STYLE::LEFT:
1989  if( ( startIsWireTerminal || startIsBusTerminal ) )
1991  else
1993  break;
1995  case ASCH_PORT_STYLE::TOP:
1998  if( ( startIsWireTerminal || startIsBusTerminal ) )
2000  else
2002  break;
2003  }
2004 
2005  label->SetFlags( IS_NEW );
2006  m_currentSheet->GetScreen()->Append( label );
2007 
2008  // This is a hack, for the case both connection points are valid: add a small wire
2009  if( ( startIsWireTerminal && endIsWireTerminal ) )
2010  {
2011  SCH_LINE* wire = new SCH_LINE( start, SCH_LAYER_ID::LAYER_WIRE );
2012  wire->SetEndPoint( end );
2013  wire->SetLineWidth( Mils2iu( 2 ) );
2014  wire->SetFlags( IS_NEW );
2015  m_currentSheet->GetScreen()->Append( wire );
2016  }
2017  else if( startIsBusTerminal && endIsBusTerminal )
2018  {
2019  SCH_LINE* wire = new SCH_LINE( start, SCH_LAYER_ID::LAYER_BUS );
2020  wire->SetEndPoint( end );
2021  wire->SetLineWidth( Mils2iu( 2 ) );
2022  wire->SetFlags( IS_NEW );
2023  m_currentSheet->GetScreen()->Append( wire );
2024  }
2025 }
2026 
2027 
2028 void SCH_ALTIUM_PLUGIN::ParseNoERC( const std::map<wxString, wxString>& aProperties )
2029 {
2030  ASCH_NO_ERC elem( aProperties );
2031 
2032  if( elem.isActive )
2033  {
2034  SCH_NO_CONNECT* noConnect = new SCH_NO_CONNECT( elem.location + m_sheetOffset );
2035 
2036  noConnect->SetFlags( IS_NEW );
2037  m_currentSheet->GetScreen()->Append( noConnect );
2038  }
2039 }
2040 
2041 
2042 void SCH_ALTIUM_PLUGIN::ParseNetLabel( const std::map<wxString, wxString>& aProperties )
2043 {
2044  ASCH_NET_LABEL elem( aProperties );
2045 
2046  SCH_LABEL* label = new SCH_LABEL( elem.location + m_sheetOffset, elem.text );
2047 
2048  switch( elem.orientation )
2049  {
2052  break;
2055  break;
2058  break;
2061  break;
2062  default:
2063  break;
2064  }
2065 
2066  label->SetFlags( IS_NEW );
2067  m_currentSheet->GetScreen()->Append( label );
2068 }
2069 
2070 
2071 void SCH_ALTIUM_PLUGIN::ParseBus( const std::map<wxString, wxString>& aProperties )
2072 {
2073  ASCH_BUS elem( aProperties );
2074 
2075  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
2076  {
2077  SCH_LINE* bus = new SCH_LINE( elem.points.at( i ) + m_sheetOffset,
2079  bus->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
2080  bus->SetLineWidth( elem.lineWidth );
2081 
2082  bus->SetFlags( IS_NEW );
2083  m_currentSheet->GetScreen()->Append( bus );
2084  }
2085 }
2086 
2087 
2088 void SCH_ALTIUM_PLUGIN::ParseWire( const std::map<wxString, wxString>& aProperties )
2089 {
2090  ASCH_WIRE elem( aProperties );
2091 
2092  for( size_t i = 0; i + 1 < elem.points.size(); i++ )
2093  {
2094  SCH_LINE* wire =
2095  new SCH_LINE( elem.points.at( i ) + m_sheetOffset, SCH_LAYER_ID::LAYER_WIRE );
2096  wire->SetEndPoint( elem.points.at( i + 1 ) + m_sheetOffset );
2097  wire->SetLineWidth( elem.lineWidth );
2098 
2099  wire->SetFlags( IS_NEW );
2100  m_currentSheet->GetScreen()->Append( wire );
2101  }
2102 }
2103 
2104 
2105 void SCH_ALTIUM_PLUGIN::ParseJunction( const std::map<wxString, wxString>& aProperties )
2106 {
2107  ASCH_JUNCTION elem( aProperties );
2108 
2109  SCH_JUNCTION* junction = new SCH_JUNCTION( elem.location + m_sheetOffset );
2110 
2111  junction->SetFlags( IS_NEW );
2112  m_currentSheet->GetScreen()->Append( junction );
2113 }
2114 
2115 
2116 void SCH_ALTIUM_PLUGIN::ParseImage( const std::map<wxString, wxString>& aProperties )
2117 {
2118  ASCH_IMAGE elem( aProperties );
2119 
2120  wxPoint center = ( elem.location + elem.corner ) / 2 + m_sheetOffset;
2121  std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>( center );
2122 
2123  if( elem.embedimage )
2124  {
2125  const ASCH_STORAGE_FILE* storageFile = GetFileFromStorage( elem.filename );
2126 
2127  if( !storageFile )
2128  {
2129  wxString msg = wxString::Format( _( "Embedded file %s not found in storage." ),
2130  elem.filename );
2132  return;
2133  }
2134 
2135  wxString storagePath = wxFileName::CreateTempFileName( "kicad_import_" );
2136 
2137  // As wxZlibInputStream is not seekable, we need to write a temporary file
2138  wxMemoryInputStream fileStream( storageFile->data.data(), storageFile->data.size() );
2139  wxZlibInputStream zlibInputStream( fileStream );
2140  wxFFileOutputStream outputStream( storagePath );
2141  outputStream.Write( zlibInputStream );
2142  outputStream.Close();
2143 
2144  if( !bitmap->ReadImageFile( storagePath ) )
2145  {
2146  m_reporter->Report( wxString::Format( _( "Error reading image %s." ), storagePath ),
2148  return;
2149  }
2150 
2151  // Remove temporary file
2152  wxRemoveFile( storagePath );
2153  }
2154  else
2155  {
2156  if( !wxFileExists( elem.filename ) )
2157  {
2158  m_reporter->Report( wxString::Format( _( "File not found %s." ), elem.filename ),
2160  return;
2161  }
2162 
2163  if( !bitmap->ReadImageFile( elem.filename ) )
2164  {
2165  m_reporter->Report( wxString::Format( _( "Error reading image %s." ), elem.filename ),
2167  return;
2168  }
2169  }
2170 
2171  // we only support one scale, thus we need to select one in case it does not keep aspect ratio
2172  wxSize currentImageSize = bitmap->GetSize();
2173  wxPoint expectedImageSize = elem.location - elem.corner;
2174  double scaleX = std::abs( static_cast<double>( expectedImageSize.x ) / currentImageSize.x );
2175  double scaleY = std::abs( static_cast<double>( expectedImageSize.y ) / currentImageSize.y );
2176  bitmap->SetImageScale( std::min( scaleX, scaleY ) );
2177 
2178  bitmap->SetFlags( IS_NEW );
2179  m_currentSheet->GetScreen()->Append( bitmap.release() );
2180 }
2181 
2182 
2183 void SCH_ALTIUM_PLUGIN::ParseSheet( const std::map<wxString, wxString>& aProperties )
2184 {
2185  m_altiumSheet = std::make_unique<ASCH_SHEET>( aProperties );
2186 
2187  PAGE_INFO pageInfo;
2188 
2189  bool isPortrait = m_altiumSheet->sheetOrientation == ASCH_SHEET_WORKSPACEORIENTATION::PORTRAIT;
2190 
2191  switch( m_altiumSheet->sheetSize )
2192  {
2193  default:
2194  case ASCH_SHEET_SIZE::A4: pageInfo.SetType( "A4", isPortrait ); break;
2195  case ASCH_SHEET_SIZE::A3: pageInfo.SetType( "A3", isPortrait ); break;
2196  case ASCH_SHEET_SIZE::A2: pageInfo.SetType( "A2", isPortrait ); break;
2197  case ASCH_SHEET_SIZE::A1: pageInfo.SetType( "A1", isPortrait ); break;
2198  case ASCH_SHEET_SIZE::A0: pageInfo.SetType( "A0", isPortrait ); break;
2199  case ASCH_SHEET_SIZE::A: pageInfo.SetType( "A", isPortrait ); break;
2200  case ASCH_SHEET_SIZE::B: pageInfo.SetType( "B", isPortrait ); break;
2201  case ASCH_SHEET_SIZE::C: pageInfo.SetType( "C", isPortrait ); break;
2202  case ASCH_SHEET_SIZE::D: pageInfo.SetType( "D", isPortrait ); break;
2203  case ASCH_SHEET_SIZE::E: pageInfo.SetType( "E", isPortrait ); break;
2204  case ASCH_SHEET_SIZE::LETTER: pageInfo.SetType( "USLetter", isPortrait ); break;
2205  case ASCH_SHEET_SIZE::LEGAL: pageInfo.SetType( "USLegal", isPortrait ); break;
2206  case ASCH_SHEET_SIZE::TABLOID: pageInfo.SetType( "A3", isPortrait ); break;
2207  case ASCH_SHEET_SIZE::ORCAD_A: pageInfo.SetType( "A", isPortrait ); break;
2208  case ASCH_SHEET_SIZE::ORCAD_B: pageInfo.SetType( "B", isPortrait ); break;
2209  case ASCH_SHEET_SIZE::ORCAD_C: pageInfo.SetType( "C", isPortrait ); break;
2210  case ASCH_SHEET_SIZE::ORCAD_D: pageInfo.SetType( "D", isPortrait ); break;
2211  case ASCH_SHEET_SIZE::ORCAD_E: pageInfo.SetType( "E", isPortrait ); break;
2212  }
2213 
2214  m_currentSheet->GetScreen()->SetPageSettings( pageInfo );
2215 
2216  m_sheetOffset = { 0, pageInfo.GetHeightIU() };
2217 }
2218 
2219 
2220 void SCH_ALTIUM_PLUGIN::ParseSheetName( const std::map<wxString, wxString>& aProperties )
2221 {
2222  ASCH_SHEET_NAME elem( aProperties );
2223 
2224  const auto& sheetIt = m_sheets.find( elem.ownerindex );
2225 
2226  if( sheetIt == m_sheets.end() )
2227  {
2228  m_reporter->Report( wxString::Format( _( "Sheetname's owner (%d) not found." ),
2229  elem.ownerindex ),
2231  return;
2232  }
2233 
2234  SCH_FIELD& sheetNameField = sheetIt->second->GetFields()[SHEETNAME];
2235 
2236  sheetNameField.SetPosition( elem.location + m_sheetOffset );
2237  sheetNameField.SetText( elem.text );
2238  sheetNameField.SetVisible( !elem.isHidden );
2240 }
2241 
2242 
2243 void SCH_ALTIUM_PLUGIN::ParseFileName( const std::map<wxString, wxString>& aProperties )
2244 {
2245  ASCH_FILE_NAME elem( aProperties );
2246 
2247  const auto& sheetIt = m_sheets.find( elem.ownerindex );
2248 
2249  if( sheetIt == m_sheets.end() )
2250  {
2251  m_reporter->Report( wxString::Format( _( "Filename's owner (%d) not found." ),
2252  elem.ownerindex ),
2254  return;
2255  }
2256 
2257  SCH_FIELD& filenameField = sheetIt->second->GetFields()[SHEETFILENAME];
2258 
2259  filenameField.SetPosition( elem.location + m_sheetOffset );
2260 
2261  // If last symbols are ".sChDoC", change them to ".kicad_sch"
2262  if( ( elem.text.Right( GetFileExtension().length() + 1 ).Lower() )
2263  == ( "." + GetFileExtension().Lower() ) )
2264  {
2265  elem.text.RemoveLast( GetFileExtension().length() );
2267  }
2268 
2269  filenameField.SetText( elem.text );
2270 
2271  filenameField.SetVisible( !elem.isHidden );
2273 }
2274 
2275 
2276 void SCH_ALTIUM_PLUGIN::ParseDesignator( const std::map<wxString, wxString>& aProperties )
2277 {
2278  ASCH_DESIGNATOR elem( aProperties );
2279 
2280  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
2281 
2282  if( libSymbolIt == m_libSymbols.end() )
2283  {
2284  // TODO: e.g. can depend on Template (RECORD=39
2285  m_reporter->Report( wxString::Format( _( "Designator's owner (%d) not found." ),
2286  elem.ownerindex ),
2288  return;
2289  }
2290 
2291  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
2292  SCH_SHEET_PATH sheetpath;
2294 
2295  symbol->SetRef( &sheetpath, elem.text );
2296 
2297  SCH_FIELD* refField = symbol->GetField( REFERENCE_FIELD );
2298 
2299  refField->SetPosition( elem.location + m_sheetOffset );
2300  refField->SetVisible( true );
2301  SetTextPositioning( refField, elem.justification, elem.orientation );
2302 }
2303 
2304 
2305 void SCH_ALTIUM_PLUGIN::ParseBusEntry( const std::map<wxString, wxString>& aProperties )
2306 {
2307  ASCH_BUS_ENTRY elem( aProperties );
2308 
2309  SCH_BUS_WIRE_ENTRY* busWireEntry = new SCH_BUS_WIRE_ENTRY( elem.location + m_sheetOffset );
2310 
2311  wxPoint vector = elem.corner - elem.location;
2312  busWireEntry->SetSize( { vector.x, vector.y } );
2313 
2314  busWireEntry->SetFlags( IS_NEW );
2315  m_currentSheet->GetScreen()->Append( busWireEntry );
2316 }
2317 
2318 
2319 void SCH_ALTIUM_PLUGIN::ParseParameter( const std::map<wxString, wxString>& aProperties )
2320 {
2321  ASCH_PARAMETER elem( aProperties );
2322 
2323  // TODO: fill in replacements from variant, sheet and project
2324  std::map<wxString, wxString> variableMap = {
2325  { "COMMENT", "VALUE" },
2326  { "VALUE", "ALTIUM_VALUE" },
2327  };
2328 
2329  if( elem.ownerindex <= 0 && elem.ownerpartid == ALTIUM_COMPONENT_NONE )
2330  {
2331  // This is some sheet parameter
2332  if( elem.text == "*" )
2333  return; // indicates parameter not set?
2334 
2335  wxString paramName = elem.name.Upper();
2336 
2337  if( paramName == "SHEETNUMBER" )
2338  {
2339  SCH_SHEET_PATH sheetpath;
2341 
2342  m_rootSheet->SetPageNumber( sheetpath, elem.text );
2343  }
2344  else if( paramName == "TITLE" )
2345  {
2346  m_currentTitleBlock->SetTitle( elem.text );
2347  }
2348  else if( paramName == "REVISION" )
2349  {
2350  m_currentTitleBlock->SetRevision( elem.text );
2351  }
2352  else if( paramName == "DATE" )
2353  {
2354  m_currentTitleBlock->SetDate( elem.text );
2355  }
2356  else if( paramName == "COMPANYNAME" )
2357  {
2358  m_currentTitleBlock->SetCompany( elem.text );
2359  }
2360  else
2361  {
2362  m_schematic->Prj().GetTextVars()[ paramName ] = elem.text;
2363  }
2364  }
2365  else
2366  {
2367  const auto& libSymbolIt = m_libSymbols.find( elem.ownerindex );
2368 
2369  if( libSymbolIt == m_libSymbols.end() )
2370  {
2371  // TODO: e.g. can depend on Template (RECORD=39
2372  return;
2373  }
2374 
2375  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
2376  SCH_FIELD* field = nullptr;
2377 
2378  if( elem.name.Upper() == "COMMENT" )
2379  field = symbol->GetField( VALUE_FIELD );
2380  else
2381  {
2382  int fieldIdx = symbol->GetFieldCount();
2383  wxString fieldName = elem.name.Upper();
2384 
2385  if( fieldName == "VALUE" )
2386  fieldName = "ALTIUM_VALUE";
2387 
2388  field = symbol->AddField( SCH_FIELD( wxPoint(), fieldIdx, symbol, fieldName ) );
2389  }
2390 
2391  wxString kicadText = AltiumSpecialStringsToKiCadVariables( elem.text, variableMap );
2392  field->SetText( kicadText );
2393  field->SetPosition( elem.location + m_sheetOffset );
2394  field->SetVisible( !elem.isHidden );
2395  SetTextPositioning( field, elem.justification, elem.orientation );
2396  }
2397 }
2398 
2399 
2401  const std::map<wxString, wxString>& aProperties )
2402 {
2403  ASCH_IMPLEMENTATION_LIST elem( aProperties );
2404 
2405  m_altiumImplementationList.emplace( aIndex, elem.ownerindex );
2406 }
2407 
2408 
2409 void SCH_ALTIUM_PLUGIN::ParseImplementation( const std::map<wxString, wxString>& aProperties )
2410 {
2411  ASCH_IMPLEMENTATION elem( aProperties );
2412 
2413  // Only get footprint, currently assigned only
2414  if( ( elem.type == "PCBLIB" ) && ( elem.isCurrent ) )
2415  {
2416  const auto& implementationOwnerIt = m_altiumImplementationList.find( elem.ownerindex );
2417 
2418  if( implementationOwnerIt == m_altiumImplementationList.end() )
2419  {
2420  m_reporter->Report( wxString::Format( _( "Implementation's owner (%d) not found." ),
2421  elem.ownerindex ),
2423  return;
2424  }
2425 
2426  const auto& libSymbolIt = m_libSymbols.find( implementationOwnerIt->second );
2427 
2428  if( libSymbolIt == m_libSymbols.end() )
2429  {
2430  m_reporter->Report( wxString::Format( _( "Footprint's owner (%d) not found." ),
2431  implementationOwnerIt->second ),
2433  return;
2434  }
2435 
2436  LIB_ID fpLibId = AltiumToKiCadLibID( elem.libname, elem.name );
2437  wxArrayString fpFilters;
2438  fpFilters.Add( fpLibId.Format() );
2439 
2440  libSymbolIt->second->SetFPFilters( fpFilters ); // TODO: not ideal as we overwrite it
2441 
2442  SCH_SYMBOL* symbol = m_symbols.at( libSymbolIt->first );
2443 
2444  symbol->SetFootprint( fpLibId.Format() );
2445  }
2446 }
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:50
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 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:551
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:642
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)
SCH_FIELD * GetField(MANDATORY_FIELD_T aFieldType)
Return a mandatory field in this symbol.
Definition: sch_symbol.cpp:675
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:331
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:64
#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 SetFileName(const wxString &aFilename)
Definition: sch_sheet.h:321
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:484
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:271
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
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
void SetItalic(bool isItalic)
Definition: eda_text.h:179
int color
Definition: DXF_plotter.cpp:57
void SetFillMode(FILL_TYPE aFillMode)
Definition: lib_item.h:277
void SetValue(const SCH_SHEET_PATH *sheet, const wxString &aValue)
Definition: sch_symbol.cpp:594
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:156
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
void SetFirstRadiusAngle(int aAngle)
Definition: lib_arc.h:86
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:153
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:237
void SetLibId(const LIB_ID &aName)
Definition: sch_symbol.cpp:238
Definition: lib_pin.h:48
LIB_FIELD & GetValueField()
Return reference to the value field.
Definition: lib_symbol.cpp:977
void CalcEndPoints()
Calculate the start and end points using the center point and the two angles.
Definition: lib_arc.cpp:593
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
void SetWidth(int aWidth) override
Definition: lib_polyline.h:97
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:103
Define a library symbol object.
Definition: lib_symbol.h:96
void SetFootprint(const SCH_SHEET_PATH *sheet, const wxString &aFootprint)
Definition: sch_symbol.cpp:645
TRANSFORM & GetTransform()
Definition: sch_symbol.h:231
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
Definition: sch_symbol.cpp:257
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.
Definition: lib_symbol.cpp:985
void SetPageNumber(const SCH_SHEET_PATH &aInstance, const wxString &aPageNumber)
Set the page number for the sheet instance aInstance.
Definition: sch_sheet.cpp:1129
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:119
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:185
ASCH_RECORD_ORIENTATION orientation
void SetLineStyle(const PLOT_DASH_TYPE aStyle)
Definition: sch_line.cpp:239
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:721
void SetBackgroundColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:115
Field Value of part, i.e. "3.3K".
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:114
void ParseLine(const std::map< wxString, wxString > &aProperties)
void SetWidth(int aWidth) override
Definition: lib_rectangle.h:79
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:314
int GetFieldCount() const
Return the number of fields in this symbol.
Definition: sch_symbol.h:421
std::unique_ptr< ASCH_SHEET > m_altiumSheet
void ParseSheetEntry(const std::map< wxString, wxString > &aProperties)
void SetEdge(SHEET_SIDE aEdge)
std::vector< wxPoint > points
void SetDescription(const wxString &aDescription)
Definition: lib_symbol.h:140
void SetRadius(int aRadius)
Definition: lib_circle.h:81
void SetBorderColor(KIGFX::COLOR4D aColor)
Definition: sch_sheet.h:112
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:1548
#define _(s)
int GetModifyHash() const override
Return the modification hash from the library cache.
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:653
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
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:315
void AddPoint(const wxPoint &aPoint)
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: sch_screen.h:152
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
void SetSecondRadiusAngle(int aAngle)
Definition: lib_arc.h:89
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:106
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:271
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:671
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 SetEnd(const wxPoint &aEnd)
Definition: lib_rectangle.h:81
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:144
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:201
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:418
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:481
const wxString GetFileExtension() const override
Return the file extension for the SCH_PLUGIN.
void SetRadius(int aRadius)
Definition: lib_arc.h:83
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:641
void ParseTextFrame(const std::map< wxString, wxString > &aProperties)
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 SetWidth(int aWidth) override
Definition: lib_circle.h:79
void SetPosition(const wxPoint &aPosition) override
Definition: lib_item.h:225
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 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:51
virtual void SetTextAngle(double aAngle)
Definition: eda_text.h:167
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:108
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:319
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 center
void SetWidth(int aWidth) override
Definition: lib_bezier.h:83
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:182
ASCH_PIN_SYMBOL_INNEREDGE symbolInnerEdge
void ParseNetLabel(const std::map< wxString, wxString > &aProperties)
void SetPosition(const wxPoint &aPosition) override
Definition: sch_field.cpp:689
ALTIUM_SCH_RECORD
ASCH_LABEL_JUSTIFICATION justification
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
bool HasParsingError()
void AddPoint(const wxPoint &aPoint)
Definition: lib_bezier.h:54
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:557
ASCH_LABEL_JUSTIFICATION justification
bool AddInstance(const KIID_PATH &aInstance)
Add a new instance aSheetPath to the instance list.
Definition: sch_sheet.cpp:1087
Define a bezier curve graphic body item.
Definition: lib_bezier.h:34
std::vector< wxPoint > points
const std::string KiCadSymbolLibFileExtension
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
wxString name