KiCad PCB EDA Suite
altium_parser_pcb.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  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <map>
25 #include <unordered_map>
26 
27 #include <ki_exception.h>
28 #include <math/util.h>
29 
30 #include <wx/log.h>
31 
32 #include "altium_parser_pcb.h"
34 
35 
36 ALTIUM_LAYER altium_layer_from_name( const wxString& aName )
37 {
38  static const std::unordered_map<std::string, ALTIUM_LAYER> hash_map = {
39  { "TOP", ALTIUM_LAYER::TOP_LAYER },
40  { "MID1", ALTIUM_LAYER::MID_LAYER_1 },
41  { "MID2", ALTIUM_LAYER::MID_LAYER_2 },
42  { "MID3", ALTIUM_LAYER::MID_LAYER_3 },
43  { "MID4", ALTIUM_LAYER::MID_LAYER_4 },
44  { "MID5", ALTIUM_LAYER::MID_LAYER_5 },
45  { "MID6", ALTIUM_LAYER::MID_LAYER_6 },
46  { "MID7", ALTIUM_LAYER::MID_LAYER_7 },
47  { "MID8", ALTIUM_LAYER::MID_LAYER_8 },
48  { "MID9", ALTIUM_LAYER::MID_LAYER_9 },
49  { "MID10", ALTIUM_LAYER::MID_LAYER_10 },
50  { "MID11", ALTIUM_LAYER::MID_LAYER_11 },
51  { "MID12", ALTIUM_LAYER::MID_LAYER_12 },
52  { "MID13", ALTIUM_LAYER::MID_LAYER_13 },
53  { "MID14", ALTIUM_LAYER::MID_LAYER_14 },
54  { "MID15", ALTIUM_LAYER::MID_LAYER_15 },
55  { "MID16", ALTIUM_LAYER::MID_LAYER_16 },
56  { "MID17", ALTIUM_LAYER::MID_LAYER_17 },
57  { "MID18", ALTIUM_LAYER::MID_LAYER_18 },
58  { "MID19", ALTIUM_LAYER::MID_LAYER_19 },
59  { "MID20", ALTIUM_LAYER::MID_LAYER_20 },
60  { "MID21", ALTIUM_LAYER::MID_LAYER_21 },
61  { "MID22", ALTIUM_LAYER::MID_LAYER_22 },
62  { "MID23", ALTIUM_LAYER::MID_LAYER_23 },
63  { "MID24", ALTIUM_LAYER::MID_LAYER_24 },
64  { "MID25", ALTIUM_LAYER::MID_LAYER_25 },
65  { "MID26", ALTIUM_LAYER::MID_LAYER_26 },
66  { "MID27", ALTIUM_LAYER::MID_LAYER_27 },
67  { "MID28", ALTIUM_LAYER::MID_LAYER_28 },
68  { "MID29", ALTIUM_LAYER::MID_LAYER_29 },
69  { "MID30", ALTIUM_LAYER::MID_LAYER_30 },
70  { "BOTTOM", ALTIUM_LAYER::BOTTOM_LAYER },
71 
72  { "TOPOVERLAY", ALTIUM_LAYER::TOP_OVERLAY },
73  { "BOTTOMOVERLAY", ALTIUM_LAYER::BOTTOM_OVERLAY },
74  { "TOPPASTE", ALTIUM_LAYER::TOP_PASTE },
75  { "BOTTOMPASTE", ALTIUM_LAYER::BOTTOM_PASTE },
76  { "TOPSOLDER", ALTIUM_LAYER::TOP_SOLDER },
77  { "BOTTOMSOLDER", ALTIUM_LAYER::BOTTOM_SOLDER },
78 
79  { "PLANE1", ALTIUM_LAYER::INTERNAL_PLANE_1 },
80  { "PLANE2", ALTIUM_LAYER::INTERNAL_PLANE_2 },
81  { "PLANE3", ALTIUM_LAYER::INTERNAL_PLANE_3 },
82  { "PLANE4", ALTIUM_LAYER::INTERNAL_PLANE_4 },
83  { "PLANE5", ALTIUM_LAYER::INTERNAL_PLANE_5 },
84  { "PLANE6", ALTIUM_LAYER::INTERNAL_PLANE_6 },
85  { "PLANE7", ALTIUM_LAYER::INTERNAL_PLANE_7 },
86  { "PLANE8", ALTIUM_LAYER::INTERNAL_PLANE_8 },
87  { "PLANE9", ALTIUM_LAYER::INTERNAL_PLANE_9 },
88  { "PLANE10", ALTIUM_LAYER::INTERNAL_PLANE_10 },
89  { "PLANE11", ALTIUM_LAYER::INTERNAL_PLANE_11 },
90  { "PLANE12", ALTIUM_LAYER::INTERNAL_PLANE_12 },
91  { "PLANE13", ALTIUM_LAYER::INTERNAL_PLANE_13 },
92  { "PLANE14", ALTIUM_LAYER::INTERNAL_PLANE_14 },
93  { "PLANE15", ALTIUM_LAYER::INTERNAL_PLANE_15 },
94  { "PLANE16", ALTIUM_LAYER::INTERNAL_PLANE_16 },
95 
96  { "DRILLGUIDE", ALTIUM_LAYER::DRILL_GUIDE },
97  { "KEEPOUT", ALTIUM_LAYER::KEEP_OUT_LAYER },
98 
99  { "MECHANICAL1", ALTIUM_LAYER::MECHANICAL_1 },
100  { "MECHANICAL2", ALTIUM_LAYER::MECHANICAL_2 },
101  { "MECHANICAL3", ALTIUM_LAYER::MECHANICAL_3 },
102  { "MECHANICAL4", ALTIUM_LAYER::MECHANICAL_4 },
103  { "MECHANICAL5", ALTIUM_LAYER::MECHANICAL_5 },
104  { "MECHANICAL6", ALTIUM_LAYER::MECHANICAL_6 },
105  { "MECHANICAL7", ALTIUM_LAYER::MECHANICAL_7 },
106  { "MECHANICAL8", ALTIUM_LAYER::MECHANICAL_8 },
107  { "MECHANICAL9", ALTIUM_LAYER::MECHANICAL_9 },
108  { "MECHANICAL10", ALTIUM_LAYER::MECHANICAL_10 },
109  { "MECHANICAL11", ALTIUM_LAYER::MECHANICAL_11 },
110  { "MECHANICAL12", ALTIUM_LAYER::MECHANICAL_12 },
111  { "MECHANICAL13", ALTIUM_LAYER::MECHANICAL_13 },
112  { "MECHANICAL14", ALTIUM_LAYER::MECHANICAL_14 },
113  { "MECHANICAL15", ALTIUM_LAYER::MECHANICAL_15 },
114  { "MECHANICAL16", ALTIUM_LAYER::MECHANICAL_16 },
115 
116  { "DRILLDRAWING", ALTIUM_LAYER::DRILL_DRAWING },
117  { "MULTILAYER", ALTIUM_LAYER::MULTI_LAYER },
118 
119  // FIXME: the following mapping is just a guess
120  { "CONNECTIONS", ALTIUM_LAYER::CONNECTIONS },
121  { "BACKGROUND", ALTIUM_LAYER::BACKGROUND },
122  { "DRCERRORMARKERS", ALTIUM_LAYER::DRC_ERROR_MARKERS },
123  { "SELECTIONS", ALTIUM_LAYER::SELECTIONS },
124  { "VISIBLEGRID1", ALTIUM_LAYER::VISIBLE_GRID_1 },
125  { "VISIBLEGRID2", ALTIUM_LAYER::VISIBLE_GRID_2 },
126  { "PADHOLES", ALTIUM_LAYER::PAD_HOLES },
127  { "VIAHOLES", ALTIUM_LAYER::VIA_HOLES },
128  };
129 
130  auto it = hash_map.find( std::string( aName.c_str() ) );
131 
132  if( it == hash_map.end() )
133  {
134  wxLogError( _( "Unknown mapping of the Altium layer '%s'." ), aName );
135  return ALTIUM_LAYER::UNKNOWN;
136  }
137  else
138  {
139  return it->second;
140  }
141 }
142 
143 void altium_parse_polygons( std::map<wxString, wxString>& aProps,
144  std::vector<ALTIUM_VERTICE>& aVertices )
145 {
146  for( size_t i = 0; i < std::numeric_limits<size_t>::max(); i++ )
147  {
148  const wxString si = std::to_string( i );
149 
150  const wxString vxi = "VX" + si;
151  const wxString vyi = "VY" + si;
152 
153  if( aProps.find( vxi ) == aProps.end() || aProps.find( vyi ) == aProps.end() )
154  break; // it doesn't seem like we know beforehand how many vertices are inside a polygon
155 
156  const bool isRound = ALTIUM_PARSER::ReadInt( aProps, "KIND" + si, 0 ) != 0;
157  const int32_t radius = ALTIUM_PARSER::ReadKicadUnit( aProps, "R" + si, "0mil" );
158  const double sa = ALTIUM_PARSER::ReadDouble( aProps, "SA" + si, 0. );
159  const double ea = ALTIUM_PARSER::ReadDouble( aProps, "EA" + si, 0. );
160  const wxPoint vp = wxPoint( ALTIUM_PARSER::ReadKicadUnit( aProps, vxi, "0mil" ),
161  -ALTIUM_PARSER::ReadKicadUnit( aProps, vyi, "0mil" ) );
162  const wxPoint cp = wxPoint( ALTIUM_PARSER::ReadKicadUnit( aProps, "CX" + si, "0mil" ),
163  -ALTIUM_PARSER::ReadKicadUnit( aProps, "CY" + si, "0mil" ) );
164 
165  aVertices.emplace_back( isRound, radius, sa, ea, vp, cp );
166  }
167 }
168 
170 {
171  std::map<wxString, wxString> props = aReader.ReadProperties();
172 
173  if( props.empty() )
174  THROW_IO_ERROR( "Board6 stream has no props!" );
175 
176  sheetpos = wxPoint( ALTIUM_PARSER::ReadKicadUnit( props, "SHEETX", "0mil" ),
177  -ALTIUM_PARSER::ReadKicadUnit( props, "SHEETY", "0mil" ) );
178  sheetsize = wxSize( ALTIUM_PARSER::ReadKicadUnit( props, "SHEETWIDTH", "0mil" ),
179  ALTIUM_PARSER::ReadKicadUnit( props, "SHEETHEIGHT", "0mil" ) );
180 
181  layercount = ALTIUM_PARSER::ReadInt( props, "LAYERSETSCOUNT", 1 ) + 1;
182 
183  for( size_t i = 1; i < std::numeric_limits<size_t>::max(); i++ )
184  {
185  const wxString layeri = "LAYER" + std::to_string( i );
186  const wxString layername = layeri + "NAME";
187 
188  auto layernameit = props.find( layername );
189 
190  if( layernameit == props.end() )
191  break; // it doesn't seem like we know beforehand how many vertices are inside a polygon
192 
194 
195  l.name = ALTIUM_PARSER::ReadString( props, layername, "" );
196  l.nextId = ALTIUM_PARSER::ReadInt( props, layeri + "NEXT", 0 );
197  l.prevId = ALTIUM_PARSER::ReadInt( props, layeri + "PREV", 0 );
198  l.copperthick = ALTIUM_PARSER::ReadKicadUnit( props, layeri + "COPTHICK", "1.4mil" );
199 
200  l.dielectricconst = ALTIUM_PARSER::ReadDouble( props, layeri + "DIELCONST", 0. );
201  l.dielectricthick = ALTIUM_PARSER::ReadKicadUnit( props, layeri + "DIELHEIGHT", "60mil" );
202  l.dielectricmaterial = ALTIUM_PARSER::ReadString( props, layeri + "DIELMATERIAL", "FR-4" );
203 
204  stackup.push_back( l );
205  }
206 
208 
209  if( aReader.HasParsingError() )
210  THROW_IO_ERROR( "Board6 stream was not parsed correctly!" );
211 }
212 
214 {
215  std::map<wxString, wxString> properties = aReader.ReadProperties();
216 
217  if( properties.empty() )
218  THROW_IO_ERROR( "Classes6 stream has no properties!" );
219 
220  name = ALTIUM_PARSER::ReadString( properties, "NAME", "" );
221  uniqueid = ALTIUM_PARSER::ReadString( properties, "UNIQUEID", "" );
222  kind = static_cast<ALTIUM_CLASS_KIND>( ALTIUM_PARSER::ReadInt( properties, "KIND", -1 ) );
223 
224  for( size_t i = 0; i < std::numeric_limits<size_t>::max(); i++ )
225  {
226  auto mit = properties.find( "M" + std::to_string( i ) );
227 
228  if( mit == properties.end() )
229  break; // it doesn't seem like we know beforehand how many components are in the netclass
230 
231  names.push_back( mit->second );
232  }
233 
234  if( aReader.HasParsingError() )
235  THROW_IO_ERROR( "Classes6 stream was not parsed correctly" );
236 }
237 
239 {
240  std::map<wxString, wxString> props = aReader.ReadProperties();
241 
242  if( props.empty() )
243  THROW_IO_ERROR( "Components6 stream has no props" );
244 
245  layer = altium_layer_from_name( ALTIUM_PARSER::ReadString( props, "LAYER", "" ) );
246  position = wxPoint( ALTIUM_PARSER::ReadKicadUnit( props, "X", "0mil" ),
247  -ALTIUM_PARSER::ReadKicadUnit( props, "Y", "0mil" ) );
248  rotation = ALTIUM_PARSER::ReadDouble( props, "ROTATION", 0. );
249  locked = ALTIUM_PARSER::ReadBool( props, "LOCKED", false );
250  nameon = ALTIUM_PARSER::ReadBool( props, "NAMEON", true );
251  commenton = ALTIUM_PARSER::ReadBool( props, "COMMENTON", false );
252  sourcedesignator = ALTIUM_PARSER::ReadString( props, "SOURCEDESIGNATOR", "" );
253  sourcefootprintlibrary = ALTIUM_PARSER::ReadString( props, "SOURCEFOOTPRINTLIBRARY", "" );
254  pattern = ALTIUM_PARSER::ReadString( props, "PATTERN", "" );
255 
256  sourcecomponentlibrary = ALTIUM_PARSER::ReadString( props, "SOURCECOMPONENTLIBRARY", "" );
257  sourcelibreference = ALTIUM_PARSER::ReadString( props, "SOURCELIBREFERENCE", "" );
258 
259  nameautoposition = static_cast<ALTIUM_TEXT_POSITION>(
260  ALTIUM_PARSER::ReadInt( props, "NAMEAUTOPOSITION", 0 ) );
261  commentautoposition = static_cast<ALTIUM_TEXT_POSITION>(
262  ALTIUM_PARSER::ReadInt( props, "COMMENTAUTOPOSITION", 0 ) );
263 
264  if( aReader.HasParsingError() )
265  THROW_IO_ERROR( "Components6 stream was not parsed correctly" );
266 }
267 
269 {
270  aReader.Skip( 2 );
271 
272  std::map<wxString, wxString> props = aReader.ReadProperties();
273 
274  if( props.empty() )
275  THROW_IO_ERROR( "Dimensions6 stream has no props" );
276 
277  layer = altium_layer_from_name( ALTIUM_PARSER::ReadString( props, "LAYER", "" ) );
278  kind = static_cast<ALTIUM_DIMENSION_KIND>( ALTIUM_PARSER::ReadInt( props, "DIMENSIONKIND", 0 ) );
279 
280  textformat = ALTIUM_PARSER::ReadString( props, "TEXTFORMAT", "" );
281  textprefix = ALTIUM_PARSER::ReadString( props, "TEXTPREFIX", "" );
282  textsuffix = ALTIUM_PARSER::ReadString( props, "TEXTSUFFIX", "" );
283 
284  height = ALTIUM_PARSER::ReadKicadUnit( props, "HEIGHT", "0mil" );
285  angle = ALTIUM_PARSER::ReadDouble( props, "ANGLE", 0. );
286 
287  linewidth = ALTIUM_PARSER::ReadKicadUnit( props, "LINEWIDTH", "10mil" );
288  textheight = ALTIUM_PARSER::ReadKicadUnit( props, "TEXTHEIGHT", "10mil" );
289  textlinewidth = ALTIUM_PARSER::ReadKicadUnit( props, "TEXTLINEWIDTH", "6mil" );
290  textprecision = ALTIUM_PARSER::ReadInt( props, "TEXTPRECISION", 2 );
291  textbold = ALTIUM_PARSER::ReadBool( props, "TEXTLINEWIDTH", false );
292  textitalic = ALTIUM_PARSER::ReadBool( props, "ITALIC", false );
293  textgap = ALTIUM_PARSER::ReadKicadUnit( props, "TEXTGAP", "10mil" );
294 
295  arrowsize = ALTIUM_PARSER::ReadKicadUnit( props, "ARROWSIZE", "60mil" );
296 
297  wxString text_position_raw = ALTIUM_PARSER::ReadString( props, "TEXTPOSITION", "" );
298 
299  xy1 = wxPoint( ALTIUM_PARSER::ReadKicadUnit( props, "X1", "0mil" ),
300  -ALTIUM_PARSER::ReadKicadUnit( props, "Y1", "0mil" ) );
301 
302  int refcount = ALTIUM_PARSER::ReadInt( props, "REFERENCES_COUNT", 0 );
303 
304  for( int i = 0; i < refcount; i++ )
305  {
306  const std::string refi = "REFERENCE" + std::to_string( i ) + "POINT";
307  referencePoint.emplace_back( ALTIUM_PARSER::ReadKicadUnit( props, refi + "X", "0mil" ),
308  -ALTIUM_PARSER::ReadKicadUnit( props, refi + "Y", "0mil" ) );
309  }
310 
311  for( size_t i = 1; i < std::numeric_limits<size_t>::max(); i++ )
312  {
313  const std::string texti = "TEXT" + std::to_string( i );
314  const std::string textix = texti + "X";
315  const std::string textiy = texti + "Y";
316 
317  if( props.find( textix ) == props.end() || props.find( textiy ) == props.end() )
318  break; // it doesn't seem like we know beforehand how many vertices are inside a polygon
319 
320  textPoint.emplace_back( ALTIUM_PARSER::ReadKicadUnit( props, textix, "0mil" ),
321  -ALTIUM_PARSER::ReadKicadUnit( props, textiy, "0mil" ) );
322  }
323 
324  wxString dimensionunit = ALTIUM_PARSER::ReadString( props, "TEXTDIMENSIONUNIT", "Millimeters" );
325 
326  if( dimensionunit == "Inches" ) textunit = ALTIUM_UNIT::INCHES;
327  else if( dimensionunit == "Mils" ) textunit = ALTIUM_UNIT::MILS;
328  else if( dimensionunit == "Millimeters" ) textunit = ALTIUM_UNIT::MILLIMETERS;
329  else if( dimensionunit == "Centimeters" ) textunit = ALTIUM_UNIT::CENTIMETER;
331 
332  if( aReader.HasParsingError() )
333  THROW_IO_ERROR( "Dimensions6 stream was not parsed correctly" );
334 }
335 
337 {
338  std::map<wxString, wxString> properties = aReader.ReadProperties();
339 
340  if( properties.empty() )
341  THROW_IO_ERROR( "Classes6 stream has no properties!" );
342 
343  name = ALTIUM_PARSER::ReadString( properties, "NAME", "" );
344  id = ALTIUM_PARSER::ReadString( properties, "ID", "" );
345  isEmbedded = ALTIUM_PARSER::ReadBool( properties, "EMBED", false );
346 
347  rotation.x = ALTIUM_PARSER::ReadDouble( properties, "ROTX", 0. );
348  rotation.y = ALTIUM_PARSER::ReadDouble( properties, "ROTY", 0. );
349  rotation.z = ALTIUM_PARSER::ReadDouble( properties, "ROTZ", 0. );
350 
351  if( aReader.HasParsingError() )
352  THROW_IO_ERROR( "Classes6 stream was not parsed correctly" );
353 }
354 
356 {
357  std::map<wxString, wxString> properties = aReader.ReadProperties();
358 
359  if( properties.empty() )
360  THROW_IO_ERROR( "Nets6 stream has no properties" );
361 
362  name = ALTIUM_PARSER::ReadString( properties, "NAME", "" );
363 
364  if( aReader.HasParsingError() )
365  THROW_IO_ERROR( "Nets6 stream was not parsed correctly" );
366 }
367 
369 {
370  std::map<wxString, wxString> properties = aReader.ReadProperties();
371 
372  if( properties.empty() )
373  THROW_IO_ERROR( "Polygons6 stream has no properties" );
374 
375  layer = altium_layer_from_name( ALTIUM_PARSER::ReadString( properties, "LAYER", "" ) );
376  net = ALTIUM_PARSER::ReadInt( properties, "NET", ALTIUM_NET_UNCONNECTED );
377  locked = ALTIUM_PARSER::ReadBool( properties, "LOCKED", false );
378 
379  // TODO: kind
380 
381  gridsize = ALTIUM_PARSER::ReadKicadUnit( properties, "GRIDSIZE", "0mil" );
382  trackwidth = ALTIUM_PARSER::ReadKicadUnit( properties, "TRACKWIDTH", "0mil" );
383  minprimlength = ALTIUM_PARSER::ReadKicadUnit( properties, "MINPRIMLENGTH", "0mil" );
384  useoctagons = ALTIUM_PARSER::ReadBool( properties, "USEOCTAGONS", false );
385 
386  pourindex = ALTIUM_PARSER::ReadInt( properties, "POURINDEX", 0 );
387 
388  wxString hatchstyleraw = ALTIUM_PARSER::ReadString( properties, "HATCHSTYLE", "" );
389 
390  if( hatchstyleraw == "Solid" ) hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::SOLID;
391  else if( hatchstyleraw == "45Degree" ) hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::DEGREE_45;
392  else if( hatchstyleraw == "90Degree" ) hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::DEGREE_90;
393  else if( hatchstyleraw == "Horizontal" ) hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::HORIZONTAL;
394  else if( hatchstyleraw == "Vertical" ) hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::VERTICAL;
395  else if( hatchstyleraw == "None" ) hatchstyle = ALTIUM_POLYGON_HATCHSTYLE::NONE;
397 
398  altium_parse_polygons( properties, vertices );
399 
400  if( aReader.HasParsingError() )
401  THROW_IO_ERROR( "Polygons6 stream was not parsed correctly" );
402 }
403 
405 {
406  // Initialize all variables and make Coverity happy
407  clearanceGap = 0;
413 
414  aReader.Skip( 2 );
415 
416  std::map<wxString, wxString> props = aReader.ReadProperties();
417 
418  if( props.empty() )
419  THROW_IO_ERROR( "Rules6 stream has no props" );
420 
421  name = ALTIUM_PARSER::ReadString( props, "NAME", "" );
422  priority = ALTIUM_PARSER::ReadInt( props, "PRIORITY", 1 );
423 
424  scope1expr = ALTIUM_PARSER::ReadString( props, "SCOPE1EXPRESSION", "" );
425  scope2expr = ALTIUM_PARSER::ReadString( props, "SCOPE2EXPRESSION", "" );
426 
427  wxString rulekind = ALTIUM_PARSER::ReadString( props, "RULEKIND", "" );
428  if( rulekind == "Clearance" )
429  {
431  clearanceGap = ALTIUM_PARSER::ReadKicadUnit( props, "GAP", "10mil" );
432  }
433  else if( rulekind == "DiffPairsRouting" )
434  {
436  }
437  else if( rulekind == "Height" )
438  {
440  }
441  else if( rulekind == "HoleSize" )
442  {
444  }
445  else if( rulekind == "HoleToHoleClearance" )
446  {
448  }
449  else if( rulekind == "Width" )
450  {
452  }
453  else if( rulekind == "PasteMaskExpansion" )
454  {
456  }
457  else if( rulekind == "PlaneClearance" )
458  {
460  planeclearanceClearance = ALTIUM_PARSER::ReadKicadUnit( props, "CLEARANCE", "10mil" );
461  }
462  else if( rulekind == "PolygonConnect" )
463  {
465  polygonconnectAirgapwidth = ALTIUM_PARSER::ReadKicadUnit( props, "AIRGAPWIDTH", "10mil" );
466  polygonconnectReliefconductorwidth = ALTIUM_PARSER::ReadKicadUnit( props, "RELIEFCONDUCTORWIDTH", "10mil" );
467  polygonconnectReliefentries = ALTIUM_PARSER::ReadInt( props, "RELIEFENTRIES", 4 );
468 
469  wxString style = ALTIUM_PARSER::ReadString( props, "CONNECTSTYLE", "" );
470 
471  if( style == "Direct" ) polygonconnectStyle = ALTIUM_CONNECT_STYLE::DIRECT;
472  else if( style == "Relief" ) polygonconnectStyle = ALTIUM_CONNECT_STYLE::RELIEF;
473  else if( style == "NoConnect" ) polygonconnectStyle = ALTIUM_CONNECT_STYLE::NONE;
475  }
476  else
477  {
479  }
480 
481  if( aReader.HasParsingError() )
482  THROW_IO_ERROR( "Rules6 stream was not parsed correctly" );
483 }
484 
486 {
487  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
488  if( recordtype != ALTIUM_RECORD::ARC )
489  {
490  THROW_IO_ERROR( "Arcs6 stream has invalid recordtype" );
491  }
492 
493  // Subrecord 1
494  aReader.ReadAndSetSubrecordLength();
495 
496  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
497 
498  uint8_t flags1 = aReader.Read<uint8_t>();
499  is_locked = ( flags1 & 0x04 ) == 0;
500  is_polygonoutline = ( flags1 & 0x02 ) != 0;
501 
502  uint8_t flags2 = aReader.Read<uint8_t>();
503  is_keepout = flags2 == 2;
504 
505  net = aReader.Read<uint16_t>();
506  subpolyindex = aReader.Read<uint16_t>();
507  component = aReader.Read<uint16_t>();
508  aReader.Skip( 4 );
509  center = aReader.ReadWxPoint();
510  radius = aReader.ReadKicadUnit();
511  startangle = aReader.Read<double>();
512  endangle = aReader.Read<double>();
513  width = aReader.ReadKicadUnit();
514 
515  aReader.SkipSubrecord();
516 
517  if( aReader.HasParsingError() )
518  {
519  THROW_IO_ERROR( "Arcs6 stream was not parsed correctly" );
520  }
521 }
522 
524 {
525  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
526 
527  if( recordtype != ALTIUM_RECORD::MODEL )
528  THROW_IO_ERROR( "ComponentsBodies6 stream has invalid recordtype" );
529 
530  aReader.ReadAndSetSubrecordLength();
531 
532  aReader.Skip( 7 );
533  component = aReader.Read<uint16_t>();
534  aReader.Skip( 9 );
535 
536  std::map<wxString, wxString> properties = aReader.ReadProperties();
537 
538  if( properties.empty() )
539  THROW_IO_ERROR( "ComponentsBodies6 stream has no properties" );
540 
541  modelName = ALTIUM_PARSER::ReadString( properties, "MODEL.NAME", "" );
542  modelId = ALTIUM_PARSER::ReadString( properties, "MODELID", "" );
543  modelIsEmbedded = ALTIUM_PARSER::ReadBool( properties, "MODEL.EMBED", false );
544 
545  modelPosition.x = ALTIUM_PARSER::ReadKicadUnit( properties, "MODEL.2D.X", "0mil" );
546  modelPosition.y = -ALTIUM_PARSER::ReadKicadUnit( properties, "MODEL.2D.Y", "0mil" );
547  modelPosition.z = ALTIUM_PARSER::ReadKicadUnit( properties, "MODEL.3D.DZ", "0mil" );
548 
549  modelRotation.x = ALTIUM_PARSER::ReadDouble( properties, "MODEL.3D.ROTX", 0. );
550  modelRotation.y = ALTIUM_PARSER::ReadDouble( properties, "MODEL.3D.ROTY", 0. );
551  modelRotation.z = ALTIUM_PARSER::ReadDouble( properties, "MODEL.3D.ROTZ", 0. );
552 
553  rotation = ALTIUM_PARSER::ReadDouble( properties, "MODEL.2D.ROTATION", 0. );
554 
555  bodyOpacity = ALTIUM_PARSER::ReadDouble( properties, "BODYOPACITY3D", 1. );
556 
557  aReader.SkipSubrecord();
558 
559  if( aReader.HasParsingError() )
560  THROW_IO_ERROR( "Components6 stream was not parsed correctly" );
561 }
562 
564 {
565  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
566 
567  if( recordtype != ALTIUM_RECORD::PAD )
568  THROW_IO_ERROR( "Pads6 stream has invalid recordtype" );
569 
570  // Subrecord 1
571  size_t subrecord1 = aReader.ReadAndSetSubrecordLength();
572 
573  if( subrecord1 == 0 )
574  THROW_IO_ERROR( "Pads6 stream has no subrecord1 data" );
575 
576  name = aReader.ReadWxString();
577 
578  if( aReader.GetRemainingSubrecordBytes() != 0 )
579  THROW_IO_ERROR( "Pads6 stream has invalid subrecord1 length" );
580 
581  aReader.SkipSubrecord();
582 
583  // Subrecord 2
584  aReader.ReadAndSetSubrecordLength();
585  aReader.SkipSubrecord();
586 
587  // Subrecord 3
588  aReader.ReadAndSetSubrecordLength();
589  aReader.SkipSubrecord();
590 
591  // Subrecord 4
592  aReader.ReadAndSetSubrecordLength();
593  aReader.SkipSubrecord();
594 
595  // Subrecord 5
596  size_t subrecord5 = aReader.ReadAndSetSubrecordLength();
597 
598  if( subrecord5 < 114 )
599  THROW_IO_ERROR( "Pads6 stream subrecord has length < 114, which is unexpected" );
600 
601  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
604 
605  uint8_t flags1 = aReader.Read<uint8_t>();
606  is_test_fab_top = ( flags1 & 0x80 ) != 0;
607  is_tent_bottom = ( flags1 & 0x40 ) != 0;
608  is_tent_top = ( flags1 & 0x20 ) != 0;
609  is_locked = ( flags1 & 0x04 ) == 0;
610 
611  uint8_t flags2 = aReader.Read<uint8_t>();
612  is_test_fab_bottom = ( flags2 & 0x01 ) != 0;
613 
614  net = aReader.Read<uint16_t>();
615  aReader.Skip( 2 );
616  component = aReader.Read<uint16_t>();
617  aReader.Skip( 4 );
618 
619  position = aReader.ReadWxPoint();
620  topsize = aReader.ReadWxSize();
621  midsize = aReader.ReadWxSize();
622  botsize = aReader.ReadWxSize();
623  holesize = aReader.ReadKicadUnit();
624 
625  topshape = static_cast<ALTIUM_PAD_SHAPE>( aReader.Read<uint8_t>() );
626  midshape = static_cast<ALTIUM_PAD_SHAPE>( aReader.Read<uint8_t>() );
627  botshape = static_cast<ALTIUM_PAD_SHAPE>( aReader.Read<uint8_t>() );
628 
629  direction = aReader.Read<double>();
630  plated = aReader.Read<uint8_t>() != 0;
631  aReader.Skip( 1 );
632  padmode = static_cast<ALTIUM_PAD_MODE>( aReader.Read<uint8_t>() );
633  aReader.Skip( 23 );
636  aReader.Skip( 7 );
637  pastemaskexpansionmode = static_cast<ALTIUM_PAD_RULE>( aReader.Read<uint8_t>() );
638  soldermaskexpansionmode = static_cast<ALTIUM_PAD_RULE>( aReader.Read<uint8_t>() );
639  aReader.Skip( 3 );
640  holerotation = aReader.Read<double>();
641 
642  if( subrecord5 >= 120 )
643  {
644  tolayer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
645  aReader.Skip( 2 );
646  fromlayer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
647  //aReader.skip( 2 );
648  }
649  else if( subrecord5 == 171 )
650  {
651  }
652 
653  aReader.SkipSubrecord();
654 
655  // Subrecord 6
656  size_t subrecord6 = aReader.ReadAndSetSubrecordLength();
657  // Known lengths: 596, 628, 651
658  // 596 is the number of bytes read in this code-block
659  if( subrecord6 >= 596 )
660  { // TODO: detect type from something else than the size?
661  sizeAndShape = std::make_unique<APAD6_SIZE_AND_SHAPE>();
662 
663  for( wxSize& size : sizeAndShape->inner_size )
664  size.x = aReader.ReadKicadUnitX();
665 
666  for( wxSize& size : sizeAndShape->inner_size )
667  size.y = aReader.ReadKicadUnitY();
668 
669  for( ALTIUM_PAD_SHAPE& shape : sizeAndShape->inner_shape )
670  shape = static_cast<ALTIUM_PAD_SHAPE>( aReader.Read<uint8_t>() );
671 
672  aReader.Skip( 1 );
673 
674  sizeAndShape->holeshape = static_cast<ALTIUM_PAD_HOLE_SHAPE>( aReader.Read<uint8_t>() );
675  sizeAndShape->slotsize = aReader.ReadKicadUnit();
676  sizeAndShape->slotrotation = aReader.Read<double>();
677 
678  for( wxPoint& pt : sizeAndShape->holeoffset )
679  pt.x = aReader.ReadKicadUnitX();
680 
681  for( wxPoint& pt : sizeAndShape->holeoffset )
682  pt.y = aReader.ReadKicadUnitY();
683 
684  aReader.Skip( 1 );
685 
686  for( ALTIUM_PAD_SHAPE_ALT& shape : sizeAndShape->alt_shape )
687  shape = static_cast<ALTIUM_PAD_SHAPE_ALT>( aReader.Read<uint8_t>() );
688 
689  for( uint8_t& radius : sizeAndShape->cornerradius )
690  radius = aReader.Read<uint8_t>();
691  }
692  else if( subrecord6 != 0 )
693  {
694  wxLogError( _( "Pads6 stream has unexpected length for subrecord 6: %d." ), subrecord6 );
695  }
696 
697  aReader.SkipSubrecord();
698 
699  if( aReader.HasParsingError() )
700  THROW_IO_ERROR( "Pads6 stream was not parsed correctly" );
701 }
702 
704 {
705  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
706 
707  if( recordtype != ALTIUM_RECORD::VIA )
708  THROW_IO_ERROR( "Vias6 stream has invalid recordtype" );
709 
710  // Subrecord 1
711  size_t subrecord1 = aReader.ReadAndSetSubrecordLength();
712 
713  aReader.Skip( 1 );
714 
715  uint8_t flags1 = aReader.Read<uint8_t>();
716  is_test_fab_top = ( flags1 & 0x80 ) != 0;
717  is_tent_bottom = ( flags1 & 0x40 ) != 0;
718  is_tent_top = ( flags1 & 0x20 ) != 0;
719  is_locked = ( flags1 & 0x04 ) == 0;
720 
721  uint8_t flags2 = aReader.Read<uint8_t>();
722  is_test_fab_bottom = ( flags2 & 0x01 ) != 0;
723 
724  net = aReader.Read<uint16_t>();
725  aReader.Skip( 8 );
726  position = aReader.ReadWxPoint();
727  diameter = aReader.ReadKicadUnit();
728  holesize = aReader.ReadKicadUnit();
729 
730  layer_start = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
731  layer_end = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
732 
733  if( subrecord1 <= 74 )
734  {
736  }
737  else
738  {
739  aReader.Skip( 43 );
740  viamode = static_cast<ALTIUM_PAD_MODE>( aReader.Read<uint8_t>() );
741  }
742 
743  aReader.SkipSubrecord();
744 
745  if( aReader.HasParsingError() )
746  THROW_IO_ERROR( "Vias6 stream was not parsed correctly" );
747 }
748 
750 {
751  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
752 
753  if( recordtype != ALTIUM_RECORD::TRACK )
754  THROW_IO_ERROR( "Tracks6 stream has invalid recordtype" );
755 
756  // Subrecord 1
757  aReader.ReadAndSetSubrecordLength();
758 
759  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
760 
761  uint8_t flags1 = aReader.Read<uint8_t>();
762  is_locked = ( flags1 & 0x04 ) == 0;
763  is_polygonoutline = ( flags1 & 0x02 ) != 0;
764 
765  uint8_t flags2 = aReader.Read<uint8_t>();
766  is_keepout = flags2 == 2;
767 
768  net = aReader.Read<uint16_t>();
769  subpolyindex = aReader.Read<uint16_t>();
770  component = aReader.Read<uint16_t>();
771  aReader.Skip( 4 );
772  start = aReader.ReadWxPoint();
773  end = aReader.ReadWxPoint();
774  width = aReader.ReadKicadUnit();
775 
776  aReader.SkipSubrecord();
777 
778  if( aReader.HasParsingError() )
779  THROW_IO_ERROR( "Tracks6 stream was not parsed correctly" );
780 }
781 
782 ATEXT6::ATEXT6( ALTIUM_PARSER& aReader, std::map<uint32_t, wxString>& aStringTable )
783 {
784  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
785 
786  if( recordtype != ALTIUM_RECORD::TEXT )
787  THROW_IO_ERROR( "Texts6 stream has invalid recordtype" );
788 
789  // Subrecord 1 - Properties
790  size_t subrecord1 = aReader.ReadAndSetSubrecordLength();
791 
792  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
793  aReader.Skip( 6 );
794  component = aReader.Read<uint16_t>();
795  aReader.Skip( 4 );
796  position = aReader.ReadWxPoint();
797  height = aReader.ReadKicadUnit();
798  aReader.Skip( 2 );
799  rotation = aReader.Read<double>();
800  isMirrored = aReader.Read<uint8_t>() != 0;
801  strokewidth = aReader.ReadKicadUnit();
802  isComment = aReader.Read<uint8_t>() != 0;
803  isDesignator = aReader.Read<uint8_t>() != 0;
804  aReader.Skip( 2 );
805  isBold = aReader.Read<uint8_t>() != 0;
806  isItalic = aReader.Read<uint8_t>() != 0;
807  aReader.Skip( 64 ); // font_name
808  isInverted = aReader.Read<uint8_t>() != 0;
809  aReader.Skip( 4 );
810  uint32_t stringIndex = aReader.Read<uint32_t>();
811  aReader.Skip( 13 );
812  textposition = static_cast<ALTIUM_TEXT_POSITION>( aReader.Read<uint8_t>() );
817  if( subrecord1 <= 230 )
819 
820  aReader.Skip( 27 );
821  fonttype = static_cast<ALTIUM_TEXT_TYPE>( aReader.Read<uint8_t>() );
822 
823  aReader.SkipSubrecord();
824 
825  // Subrecord 2 - Legacy 8bit string, max 255 chars, unknown codepage
826  aReader.ReadAndSetSubrecordLength();
827 
828  auto entry = aStringTable.find( stringIndex );
829 
830  if( entry != aStringTable.end() )
831  text = entry->second;
832  else
833  text = aReader.ReadWxString();
834 
835  // Normalize Windows line endings
836  text.Replace( "\r\n", "\n" );
837 
838  aReader.SkipSubrecord();
839 
840  if( aReader.HasParsingError() )
841  THROW_IO_ERROR( "Texts6 stream was not parsed correctly" );
842 }
843 
845 {
846  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
847 
848  if( recordtype != ALTIUM_RECORD::FILL )
849  THROW_IO_ERROR( "Fills6 stream has invalid recordtype" );
850 
851  // Subrecord 1
852  aReader.ReadAndSetSubrecordLength();
853 
854  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
855 
856  uint8_t flags1 = aReader.Read<uint8_t>();
857  is_locked = ( flags1 & 0x04 ) == 0;
858 
859  uint8_t flags2 = aReader.Read<uint8_t>();
860  is_keepout = flags2 == 2;
861 
862  net = aReader.Read<uint16_t>();
863  aReader.Skip( 2 );
864  component = aReader.Read<uint16_t>();
865  aReader.Skip( 4 );
866  pos1 = aReader.ReadWxPoint();
867  pos2 = aReader.ReadWxPoint();
868  rotation = aReader.Read<double>();
869 
870  aReader.SkipSubrecord();
871 
872  if( aReader.HasParsingError() )
873  THROW_IO_ERROR( "Fills6 stream was not parsed correctly" );
874 }
875 
876 AREGION6::AREGION6( ALTIUM_PARSER& aReader, bool aExtendedVertices )
877 {
878  ALTIUM_RECORD recordtype = static_cast<ALTIUM_RECORD>( aReader.Read<uint8_t>() );
879 
880  if( recordtype != ALTIUM_RECORD::REGION )
881  THROW_IO_ERROR( "Regions6 stream has invalid recordtype" );
882 
883  // Subrecord 1
884  aReader.ReadAndSetSubrecordLength();
885 
886  layer = static_cast<ALTIUM_LAYER>( aReader.Read<uint8_t>() );
887 
888  uint8_t flags1 = aReader.Read<uint8_t>();
889  is_locked = ( flags1 & 0x04 ) == 0;
890 
891  uint8_t flags2 = aReader.Read<uint8_t>();
892  is_keepout = flags2 == 2;
893 
894  net = aReader.Read<uint16_t>();
895  subpolyindex = aReader.Read<uint16_t>();
896  component = aReader.Read<uint16_t>();
897  aReader.Skip( 5 );
898  holecount = aReader.Read<uint16_t>();
899  aReader.Skip( 2 );
900 
901  std::map<wxString, wxString> properties = aReader.ReadProperties();
902 
903  if( properties.empty() )
904  THROW_IO_ERROR( "Regions6 stream has empty properties" );
905 
906  int pkind = ALTIUM_PARSER::ReadInt( properties, "KIND", 0 );
907  bool is_cutout = ALTIUM_PARSER::ReadBool( properties, "ISBOARDCUTOUT", false );
908 
909  is_shapebased = ALTIUM_PARSER::ReadBool( properties, "ISSHAPEBASED", false );
910 
911  // TODO: this can differ from the other subpolyindex?!
912  //subpolyindex = static_cast<uint16_t>(
913  // ALTIUM_PARSER::ReadInt( properties, "SUBPOLYINDEX", ALTIUM_POLYGON_NONE ) );
914 
915  switch( pkind )
916  {
917  case 0:
918  if( is_cutout )
919  {
921  }
922  else
923  {
925  }
926  break;
927  case 1:
929  break;
930  case 2:
931  kind = ALTIUM_REGION_KIND::UNKNOWN_2; // TODO: what kind is this?
932  break;
933  case 3:
934  kind = ALTIUM_REGION_KIND::UNKNOWN_3; // TODO: what kind is this?
935  break;
936  case 4:
938  break;
939  default:
941  break;
942  }
943 
944  uint32_t num_outline_vertices = aReader.Read<uint32_t>();
945 
946  for( uint32_t i = 0; i < num_outline_vertices; i++ )
947  {
948  if( aExtendedVertices )
949  {
950  bool isRound = aReader.Read<uint8_t>() != 0;
951  wxPoint position = aReader.ReadWxPoint();
952  wxPoint center = aReader.ReadWxPoint();
953  int32_t radius = aReader.ReadKicadUnit();
954  double angle1 = aReader.Read<double>();
955  double angle2 = aReader.Read<double>();
956  outline.emplace_back( isRound, radius, angle1, angle2, position, center );
957  }
958  else
959  {
960  // For some regions the coordinates are stored as double and not as int32_t
961  int32_t x = ALTIUM_PARSER::ConvertToKicadUnit( aReader.Read<double>() );
962  int32_t y = ALTIUM_PARSER::ConvertToKicadUnit( -aReader.Read<double>() );
963  outline.emplace_back( wxPoint( x, y ) );
964  }
965  }
966 
967  // TODO: for now we only support holes in regions where there are stored as double
968  if( !aExtendedVertices )
969  {
970  holes.resize( holecount );
971  for( uint16_t k = 0; k < holecount; k++ )
972  {
973  uint32_t num_hole_vertices = aReader.Read<uint32_t>();
974  holes.at( k ).reserve( num_hole_vertices );
975 
976  for( uint32_t i = 0; i < num_hole_vertices; i++ )
977  {
978  int32_t x = ALTIUM_PARSER::ConvertToKicadUnit( aReader.Read<double>() );
979  int32_t y = ALTIUM_PARSER::ConvertToKicadUnit( -aReader.Read<double>() );
980  holes.at( k ).emplace_back( wxPoint( x, y ) );
981  }
982  }
983  }
984 
985  aReader.SkipSubrecord();
986 
987  if( aReader.HasParsingError() )
988  THROW_IO_ERROR( "Regions6 stream was not parsed correctly" );
989 }
AREGION6(ALTIUM_PARSER &aReader, bool aExtendedVertices)
ADIMENSION6(ALTIUM_PARSER &aReader)
uint32_t textlinewidth
uint32_t linewidth
ALTIUM_LAYER tolayer
FP_3DMODEL::VECTOR3D modelPosition
int32_t soldermaskexpansionmanual
ALTIUM_RULE_KIND kind
double rotation
uint32_t holesize
uint32_t width
int planeclearanceClearance
ATEXT6(ALTIUM_PARSER &aReader, std::map< uint32_t, wxString > &aStringTable)
wxString name
bool isDesignator
bool is_locked
ALTIUM_TEXT_POSITION nameautoposition
ALTIUM_PAD_SHAPE topshape
wxPoint pos1
ALTIUM_LAYER layer
AMODEL(ALTIUM_PARSER &aReader)
wxPoint start
wxSize topsize
ALTIUM_LAYER layer
ALTIUM_DIMENSION_KIND kind
ARULE6(ALTIUM_PARSER &aReader)
ALTIUM_REGION_KIND kind
wxPoint position
double startangle
uint16_t component
bool is_test_fab_bottom
int32_t polygonconnectAirgapwidth
wxPoint center
ALTIUM_LAYER layer
std::vector< std::vector< ALTIUM_VERTICE > > holes
wxString sourcedesignator
ALTIUM_LAYER layer
ALTIUM_RECORD
ALTIUM_LAYER layer_end
ALTIUM_PAD_SHAPE
ALTIUM_PAD_RULE soldermaskexpansionmode
ALTIUM_LAYER layer
uint16_t net
wxString sourcefootprintlibrary
AVIA6(ALTIUM_PARSER &aReader)
uint16_t holecount
FP_3DMODEL::VECTOR3D rotation
wxString name
wxString sourcelibreference
wxString text
wxSize sheetsize
wxString scope2expr
bool is_tent_bottom
bool is_polygonoutline
uint32_t height
ALTIUM_PAD_SHAPE_ALT
void Skip(size_t aLength)
static double ReadDouble(const std::map< wxString, wxString > &aProps, const wxString &aKey, double aDefault)
ALTIUM_CONNECT_STYLE polygonconnectStyle
std::vector< wxString > names
int32_t trackwidth
std::vector< wxPoint > textPoint
size_t GetRemainingSubrecordBytes() const
wxString textformat
wxString sourcecomponentlibrary
uint16_t subpolyindex
wxSize ReadWxSize()
uint16_t net
APAD6(ALTIUM_PARSER &aReader)
size_t ReadAndSetSubrecordLength()
wxSize botsize
static int ReadInt(const std::map< wxString, wxString > &aProps, const wxString &aKey, int aDefault)
std::map< wxString, wxString > ReadProperties()
ALTIUM_PAD_RULE pastemaskexpansionmode
wxPoint position
uint16_t subpolyindex
double direction
wxString textsuffix
double endangle
wxPoint ReadWxPoint()
ALTIUM_CLASS_KIND kind
ALTIUM_LAYER layer
const uint16_t ALTIUM_NET_UNCONNECTED
wxSize midsize
wxString name
#define _(s)
uint16_t component
uint32_t holesize
static bool ReadBool(const std::map< wxString, wxString > &aProps, const wxString &aKey, bool aDefault)
bool is_test_fab_top
ACOMPONENTBODY6(ALTIUM_PARSER &aReader)
wxPoint sheetpos
wxString textprefix
ABOARD6(ALTIUM_PARSER &aReader)
uint16_t net
bool is_test_fab_bottom
int32_t ReadKicadUnit()
bool is_keepout
FP_3DMODEL::VECTOR3D modelRotation
bool is_locked
double rotation
bool is_polygonoutline
AFILL6(ALTIUM_PARSER &aReader)
bool is_tent_bottom
uint16_t subpolyindex
ACLASS6(ALTIUM_PARSER &aReader)
wxString uniqueid
ALTIUM_PAD_SHAPE botshape
std::vector< ALTIUM_VERTICE > vertices
ANET6(ALTIUM_PARSER &aReader)
uint32_t width
ALTIUM_TEXT_POSITION textposition
ALTIUM_LAYER layer
uint16_t net
ALTIUM_LAYER layer_start
bool is_test_fab_top
bool is_tent_top
ATRACK6(ALTIUM_PARSER &aReader)
uint32_t radius
wxPoint position
std::vector< ALTIUM_VERTICE > outline
wxString ReadWxString()
Definition: altium_parser.h:69
ALTIUM_PAD_MODE viamode
int32_t pastemaskexpansionmanual
wxString name
APOLYGON6(ALTIUM_PARSER &aReader)
uint16_t net
uint16_t component
ALTIUM_LAYER
ALTIUM_PAD_MODE padmode
ALTIUM_LAYER layer
std::unique_ptr< APAD6_SIZE_AND_SHAPE > sizeAndShape
uint16_t component
std::vector< ALTIUM_VERTICE > board_vertices
ALTIUM_UNIT textunit
static wxString ReadString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
int32_t ReadKicadUnitX()
ALTIUM_LAYER layer
ALTIUM_TEXT_POSITION commentautoposition
uint16_t component
void SkipSubrecord()
ALTIUM_PAD_SHAPE midshape
std::vector< wxPoint > referencePoint
std::vector< ABOARD6_LAYER_STACKUP > stackup
uint32_t strokewidth
bool is_tent_top
int32_t ReadKicadUnitY()
ALTIUM_LAYER altium_layer_from_name(const wxString &aName)
int32_t minprimlength
int32_t gridsize
ACOMPONENT6(ALTIUM_PARSER &aReader)
uint32_t textheight
void altium_parse_polygons(std::map< wxString, wxString > &aProps, std::vector< ALTIUM_VERTICE > &aVertices)
ALTIUM_POLYGON_HATCHSTYLE hatchstyle
uint16_t component
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
bool HasParsingError()
ALTIUM_TEXT_TYPE fonttype
int32_t textprecision
wxPoint pos2
uint32_t diameter
AARC6(ALTIUM_PARSER &aReader)
double holerotation
bool is_locked
ALTIUM_LAYER fromlayer
wxString name
uint16_t net
static int32_t ConvertToKicadUnit(const double aValue)
wxString scope1expr
int32_t polygonconnectReliefconductorwidth
int32_t pourindex
int polygonconnectReliefentries