KiCad PCB EDA Suite
Loading...
Searching...
No Matches
cadstar_pcb_archive_parser.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 Roberto Fernandez Bautista <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * 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, see <https://www.gnu.org/licenses/>.
19 */
20
25
26#include <base_units.h>
28#include <macros.h>
29#include <progress_reporter.h>
30#include <wx/log.h>
31#include <wx/translation.h>
32
33
35{
37 m_progressReporter->BeginPhase( 0 ); // Read file
38
39 m_rootNode = LoadArchiveFile( Filename, wxT( "CADSTARPCB" ), m_progressReporter );
40
42 {
43 m_progressReporter->BeginPhase( 1 ); // Parse File
44
45 std::vector<wxString> subNodeChildrenToCount = { wxT( "LIBRARY" ), wxT( "PARTS" ),
46 wxT( "LAYOUT" ) };
47
48 long numOfSteps = GetNumberOfStepsForReporting( m_rootNode, subNodeChildrenToCount );
49 m_progressReporter->SetMaxProgress( numOfSteps );
50 }
51
52 m_context.CheckPointCallback = [&](){ checkPoint(); };
53
54 XNODE* cNode = m_rootNode->GetChildren();
55
56 if( !cNode )
57 THROW_MISSING_NODE_IO_ERROR( wxT( "HEADER" ), wxT( "CADSTARPCB" ) );
58
59 for( ; cNode; cNode = cNode->GetNext() )
60 {
61 if( cNode->GetName() == wxT( "HEADER" ) )
62 {
63 Header.Parse( cNode, &m_context );
64
65 switch( Header.Resolution )
66 {
69 break;
70
71 default:
72 wxASSERT_MSG( true, wxT( "Unknown File Resolution" ) );
73 break;
74 }
75
76 if( aLibrary && Header.Format.Type != wxT( "LIBRARY" ) )
77 {
78 THROW_IO_ERROR( wxT( "The selected file is not a valid CADSTAR library file." ) );
79 }
80 else if( !aLibrary && Header.Format.Type != wxT( "LAYOUT" ) )
81 {
82 if( Header.Format.Type == wxT( "LIBRARY" ) )
83 {
84 THROW_IO_ERROR( wxT( "The selected file is a CADSTAR library file (as opposed to a layout file). "
85 "You can import this library by adding it to the library table." ) );
86 }
87 else
88 {
89 THROW_IO_ERROR( wxT( "The selected file is an unknown CADSTAR format so cannot be imported into "
90 "KiCad." ) );
91 }
92 }
93 }
94 else if( cNode->GetName() == wxT( "ASSIGNMENTS" ) )
95 {
96 Assignments.Parse( cNode, &m_context );
97 }
98 else if( cNode->GetName() == wxT( "LIBRARY" ) )
99 {
100 Library.Parse( cNode, &m_context );
101 }
102 else if( cNode->GetName() == wxT( "DEFAULTS" ) )
103 {
104 // No design information here (no need to parse)
105 // Only contains CADSTAR configuration data such as default shapes, text and units
106 // In future some of this could be converted to KiCad but limited value
107 }
108 else if( cNode->GetName() == wxT( "PARTS" ) )
109 {
110 Parts.Parse( cNode, &m_context );
111 }
112 else if( cNode->GetName() == wxT( "LAYOUT" ) )
113 {
114 Layout.Parse( cNode, &m_context );
115 }
116 else if( cNode->GetName() == wxT( "DISPLAY" ) )
117 {
118 // No design information here (no need to parse)
119 // Contains CADSTAR Display settings such as layer/element colours and visibility.
120 // In the future these settings could be converted to KiCad
121 }
122 else
123 {
124 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "[root]" ) );
125 }
126
127 checkPoint();
128 }
129
130 delete m_rootNode;
131 m_rootNode = nullptr;
132}
133
134
136{
137 wxASSERT( aNode->GetName() == wxT( "ASSIGNMENTS" ) );
138
139 XNODE* cNode = aNode->GetChildren();
140
141 if( !cNode )
142 THROW_MISSING_NODE_IO_ERROR( wxT( "TECHNOLOGY" ), wxT( "ASSIGNMENTS" ) );
143
144 for( ; cNode; cNode = cNode->GetNext() )
145 {
146 if( cNode->GetName() == wxT( "LAYERDEFS" ) )
147 Layerdefs.Parse( cNode, aContext );
148 else if( cNode->GetName() == wxT( "CODEDEFS" ) )
149 Codedefs.Parse( cNode, aContext );
150 else if( cNode->GetName() == wxT( "TECHNOLOGY" ) )
151 Technology.Parse( cNode, aContext );
152 else if( cNode->GetName() == wxT( "GRIDS" ) )
153 Grids.Parse( cNode, aContext );
154 else if( cNode->GetName() == wxT( "NETCLASSEDITATTRIBSETTINGS" ) )
156 else if( cNode->GetName() == wxT( "SPCCLASSEDITATTRIBSETTINGS" ) )
158 else
159 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
160 }
161}
162
163
165{
166 wxASSERT( aNode->GetName() == wxT( "LAYERDEFS" ) );
167
168 wxXmlAttribute* xmlAttribute = nullptr;
169
170 XNODE* cNode = aNode->GetChildren();
171
172 if( !cNode )
173 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "LAYERSTACK" ), wxT( "LAYERDEFS" ) );
174
175 for( ; cNode; cNode = cNode->GetNext() )
176 {
177 wxString nodeName = cNode->GetName();
178
179 if( nodeName == wxT( "LAYERSTACK" ) )
180 {
181 xmlAttribute = cNode->GetAttributes();
182
183 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
184 {
185 if( !IsValidAttribute( xmlAttribute ) )
186 continue;
187 else
188 LayerStack.push_back( (LAYER_ID) xmlAttribute->GetValue() );
189 }
190
191 CheckNoChildNodes( cNode );
192 }
193 else if( nodeName == wxT( "MATERIAL" ) )
194 {
195 MATERIAL material;
196 material.Parse( cNode, aContext );
197 Materials.insert( std::make_pair( material.ID, material ) );
198 }
199 else if( nodeName == wxT( "LAYER" ) )
200 {
201 LAYER layer;
202 layer.Parse( cNode, aContext );
203 Layers.insert( std::make_pair( layer.ID, layer ) );
204 }
205 else if( nodeName == wxT( "SWAPPAIR" ) )
206 {
207 LAYER_ID layerId = (LAYER_ID) GetXmlAttributeIDString( cNode, 0 );
208 LAYER_ID swapLayerId = (LAYER_ID) GetXmlAttributeIDString( cNode, 1 );
209
210 Layers[layerId].SwapLayerID = swapLayerId;
211 }
212 else
213 {
214 WARN_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
215 }
216 }
217}
218
219
221{
222 wxASSERT( aNode->GetName() == wxT( "RULESET" ) );
223
224 ID = GetXmlAttributeIDString( aNode, 0 );
225 Name = GetXmlAttributeIDString( aNode, 1 );
226
227 XNODE* cNode = aNode->GetChildren();
228
229 for( ; cNode; cNode = cNode->GetNext() )
230 {
231 wxString nodeName = cNode->GetName();
232
233 if( nodeName == wxT( "ROUCODEREF" ) )
234 {
236 }
237 else if( nodeName == wxT( "VIACODEREF" ) )
238 {
240 }
241 else if( nodeName == wxT( "SPACINGCODE" ) )
242 {
243 SPACINGCODE spacingcode;
244 spacingcode.Parse( cNode, aContext );
245 SpacingCodes.insert( std::make_pair( spacingcode.ID, spacingcode ) );
246 }
247 else
248 {
249 WARN_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
250 }
251 }
252}
253
254
256{
257 wxASSERT( aNode->GetName() == wxT( "CODEDEFS" ) );
258
259 XNODE* cNode = aNode->GetChildren();
260
261 for( ; cNode; cNode = cNode->GetNext() )
262 {
263 wxString nodeName = cNode->GetName();
264
265 if( ParseSubNode( cNode, aContext ) ) // in CADSTAR_ARCHIVE_PARSER::CODEDEFS
266 {
267 }
268 else if( nodeName == wxT( "COPPERCODE" ) )
269 {
270 COPPERCODE coppercode;
271 coppercode.Parse( cNode, aContext );
272 CopperCodes.insert( std::make_pair( coppercode.ID, coppercode ) );
273 }
274 else if( nodeName == wxT( "SPACINGCODE" ) )
275 {
276 SPACINGCODE spacingcode;
277 spacingcode.Parse( cNode, aContext );
278 SpacingCodes.insert( std::make_pair( spacingcode.ID, spacingcode ) );
279 }
280 else if( nodeName == wxT( "RULESET" ) )
281 {
282 RULESET ruleset;
283 ruleset.Parse( cNode, aContext );
284 Rulesets.insert( std::make_pair( ruleset.ID, ruleset ) );
285 }
286 else if( nodeName == wxT( "PADCODE" ) )
287 {
288 PADCODE padcode;
289 padcode.Parse( cNode, aContext );
290 PadCodes.insert( std::make_pair( padcode.ID, padcode ) );
291 }
292 else if( nodeName == wxT( "VIACODE" ) )
293 {
294 VIACODE viacode;
295 viacode.Parse( cNode, aContext );
296 ViaCodes.insert( std::make_pair( viacode.ID, viacode ) );
297 }
298 else if( nodeName == wxT( "LAYERPAIR" ) )
299 {
300 LAYERPAIR layerpair;
301 layerpair.Parse( cNode, aContext );
302 LayerPairs.insert( std::make_pair( layerpair.ID, layerpair ) );
303 }
304 else if( nodeName == wxT( "SPCCLASSSPACE" ) )
305 {
306 SPCCLASSSPACE spcclassspace;
307 spcclassspace.Parse( cNode, aContext );
308 SpacingClasses.push_back( spcclassspace );
309 }
310 else
311 {
312 WARN_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
313 }
314 }
315}
316
317
319{
320 wxASSERT( aNode->GetName() == wxT( "MATERIAL" ) );
321
322 ID = GetXmlAttributeIDString( aNode, 0 );
323 Name = GetXmlAttributeIDString( aNode, 1 );
324
325 wxString sType = GetXmlAttributeIDString( aNode, 2 );
326
327 if( sType == wxT( "CONSTRUCTION" ) )
328 {
330 }
331 else if( sType == wxT( "ELECTRICAL" ) )
332 {
334 }
335 else if( sType == wxT( "NONELEC" ) )
336 {
338 }
339 else
340 {
341 WARN_UNKNOWN_PARAMETER_IO_ERROR( sType, wxString::Format( wxT( "MATERIAL %s" ), Name ) );
342 }
343
344 XNODE* iNode = aNode->GetChildren();
345
346 if( !iNode )
347 {
348 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "RESISTIVITY" ),
349 wxString::Format( wxT( "MATERIAL %s" ), Name ) );
350 }
351
352 for( ; iNode; iNode = iNode->GetNext() )
353 {
354 wxString nodeName = iNode->GetName();
355
356 if( nodeName == wxT( "RELPERMIT" ) )
357 {
358 ParseChildEValue( iNode, aContext, Permittivity );
359 }
360 else if( nodeName == wxT( "LOSSTANGENT" ) )
361 {
362 ParseChildEValue( iNode, aContext, LossTangent );
363 }
364 else if( nodeName == wxT( "RESISTIVITY" ) )
365 {
366 ParseChildEValue( iNode, aContext, Resistivity );
367 }
368 else
369 {
370 WARN_UNKNOWN_NODE_IO_ERROR( nodeName, wxString::Format( wxT( "MATERIAL %s" ), Name ) );
371 }
372 }
373}
374
375
377{
378 wxASSERT( aNode->GetName() == wxT( "LAYER" ) );
379
380 ID = GetXmlAttributeIDString( aNode, 0 );
381 Name = GetXmlAttributeIDString( aNode, 1 );
382
383 XNODE* cNode = aNode->GetChildren();
384 auto processLayerMaterialDetails = [&]() {
385 XNODE* tempNode = cNode->GetChildren();
386 for( ; tempNode; tempNode = tempNode->GetNext() )
387 {
388 wxString tempNodeName = tempNode->GetName();
389
390 if( tempNodeName == wxT( "MAKE" ) || tempNodeName == wxT( "LAYERHEIGHT" ) )
391 {
392 if( tempNodeName == wxT( "LAYERHEIGHT" ) )
393 {
394 Thickness = GetXmlAttributeIDLong( tempNode, 0 );
395 }
396 else
397 {
398 MaterialId = GetXmlAttributeIDString( tempNode, 0 );
399 Thickness = GetXmlAttributeIDLong( tempNode, 1 );
400 }
401
402 XNODE* childOfTempNode = tempNode->GetChildren();
403
404 if( childOfTempNode )
405 {
406 if( childOfTempNode->GetName() == wxT( "EMBEDS" ) )
407 {
408 wxString embedsValue = GetXmlAttributeIDString( childOfTempNode, 0 );
409
410 if( embedsValue == wxT( "UPWARDS" ) )
411 {
413 }
414 else if( embedsValue == wxT( "DOWNWARDS" ) )
415 {
417 }
418 else
419 {
421 wxString::Format( wxT( "LAYER %s -> EMBEDS" ),
422 Name ) );
423 }
424 }
425 else
426 {
427 WARN_UNKNOWN_NODE_IO_ERROR( childOfTempNode->GetName(),
428 wxString::Format( wxT( "LAYER %s->MAKE" ),
429 Name ) );
430 }
431 }
432 }
433 else if( tempNodeName == wxT( "BIAS" ) )
434 {
435 wxString bias = GetXmlAttributeIDString( tempNode, 0 );
436
437 if( bias == wxT( "X_BIASED" ) )
438 {
440 }
441 else if( bias == wxT( "Y_BIASED" ) )
442 {
444 }
445 else if( bias == wxT( "ANTITRACK" ) )
446 {
448 }
449 else if( bias == wxT( "OBSTACLE" ) )
450 {
452 }
453 else if( bias == wxT( "UNBIASED" ) )
454 {
456 }
457 else
458 {
460 wxString::Format( wxT( "LAYER %s -> BIAS" ),
461 Name ) );
462 }
463 }
464 else
465 {
466 WARN_UNKNOWN_NODE_IO_ERROR( tempNodeName, wxString::Format( wxT( "LAYER %s" ),
467 Name ) );
468 }
469 }
470 };
471
472 for( ; cNode; cNode = cNode->GetNext() )
473 {
474 wxString cNodeName = cNode->GetName();
475
476 if( cNodeName == wxT( "ALLDOC" ) )
477 {
479 }
480 else if( cNodeName == wxT( "ALLELEC" ) )
481 {
483 }
484 else if( cNodeName == wxT( "ALLLAYER" ) )
485 {
487 }
488 else if( cNodeName == wxT( "ASSCOMPCOPP" ) )
489 {
491 }
492 else if( cNodeName == wxT( "JUMPERLAYER" ) )
493 {
495 }
496 else if( cNodeName == wxT( "NOLAYER" ) )
497 {
499 }
500 else if( cNodeName == wxT( "POWER" ) )
501 {
504 processLayerMaterialDetails();
505 }
506 else if( cNodeName == wxT( "DOC" ) )
507 {
509 }
510 else if( cNodeName == wxT( "CONSTRUCTION" ) )
511 {
513 processLayerMaterialDetails();
514 }
515 else if( cNodeName == wxT( "ELEC" ) )
516 {
519 processLayerMaterialDetails();
520 }
521 else if( cNodeName == wxT( "NONELEC" ) )
522 {
525 processLayerMaterialDetails();
526 }
527 else if( cNodeName == wxT( "DESCRIPTION" ) )
528 {
530 }
531 else if( cNodeName == wxT( "REFPLANE" ) )
532 {
533 ReferencePlane = true;
534 }
535 else if( cNodeName == wxT( "VLAYER" ) )
536 {
537 VariantLayer = true;
538 }
539 else if( cNodeName == wxT( "LASUBTYP" ) )
540 {
541 //Process subtype
542 wxString sSubType = GetXmlAttributeIDString( cNode, 0 );
543
544 if( sSubType == wxT( "LAYERSUBTYPE_ASSEMBLY" ) )
545 {
547 }
548 else if( sSubType == wxT( "LAYERSUBTYPE_PASTE" ) )
549 {
551 }
552 else if( sSubType == wxT( "LAYERSUBTYPE_PLACEMENT" ) )
553 {
555 }
556 else if( sSubType == wxT( "LAYERSUBTYPE_SILKSCREEN" ) )
557 {
559 }
560 else if( sSubType == wxT( "LAYERSUBTYPE_SOLDERRESIST" ) )
561 {
563 }
564 else if( sSubType == wxT( "LAYERSUBTYPE_CLEARANCE" ) )
565 {
567 }
568 else if( sSubType == wxT( "LAYERSUBTYPE_ROUT" ) )
569 {
571 }
572 else
573 {
574 WARN_UNKNOWN_PARAMETER_IO_ERROR( sSubType, wxString::Format( wxT( "LAYER %s %s" ),
575 Name, cNodeName ) );
576 }
577 }
578 else
579 {
580 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxString::Format( wxT( "LAYER %s" ), Name ) );
581 }
582 }
583}
584
585
587{
588 wxASSERT( aNode->GetName() == wxT( "COPREASSIGN" ) );
589
590 LayerID = GetXmlAttributeIDString( aNode, 0 );
591
593}
594
595
597{
598 wxASSERT( aNode->GetName() == wxT( "COPPERCODE" ) );
599
600 ID = GetXmlAttributeIDString( aNode, 0 );
601 Name = GetXmlAttributeIDString( aNode, 1 );
602
604
605 XNODE* cNode = aNode->GetChildren();
606
607 for( ; cNode; cNode = cNode->GetNext() )
608 {
609 if( cNode->GetName() == wxT( "COPREASSIGN" ) )
610 {
612 reassign.Parse( cNode, aContext );
613 Reassigns.push_back( reassign );
614 }
615 else
616 {
617 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
618 }
619 }
620}
621
622
624 PARSER_CONTEXT* aContext )
625{
626 wxASSERT( aNode->GetName() == wxT( "SPACEREASSIGN" ) );
627
628 LayerID = GetXmlAttributeIDString( aNode, 0 );
629 Spacing = GetXmlAttributeIDLong( aNode, 1 );
630
631 CheckNoChildNodes( aNode );
632}
633
634
636{
637 wxASSERT( aNode->GetName() == wxT( "SPACINGCODE" ) );
638
639 ID = GetXmlAttributeIDString( aNode, 0 );
640 Spacing = GetXmlAttributeIDLong( aNode, 1 );
641
642 XNODE* cNode = aNode->GetChildren();
643
644 for( ; cNode; cNode = cNode->GetNext() )
645 {
646 wxString cNodeName = cNode->GetName();
647
648 if( cNodeName == wxT( "SPACEREASSIGN" ) )
649 {
650 REASSIGN reassign;
651 reassign.Parse( cNode, aContext );
652 Reassigns.push_back( reassign );
653 }
654 else
655 {
656 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
657 }
658 }
659}
660
661
663{
664 if( !aNode )
665 return false;
666
667 wxString aNodeName = aNode->GetName();
668
669 if( aNodeName == wxT( "ANNULUS" ) || aNodeName == wxT( "BULLET" ) || aNodeName == wxT( "ROUND" )
670 || aNodeName == wxT( "DIAMOND" ) || aNodeName == wxT( "FINGER" )
671 || aNodeName == wxT( "OCTAGON" ) || aNodeName == wxT( "RECTANGLE" )
672 || aNodeName == wxT( "ROUNDED" ) || aNodeName == wxT( "SQUARE" ) )
673 {
674 return true;
675 }
676 else
677 {
678 return false;
679 }
680}
681
682
684{
685 wxASSERT( IsPadShape( aNode ) );
686
687 wxString aNodeName = aNode->GetName();
688
689 if( aNodeName == wxT( "ANNULUS" ) )
691 else if( aNodeName == wxT( "BULLET" ) )
693 else if( aNodeName == wxT( "ROUND" ) )
695 else if( aNodeName == wxT( "DIAMOND" ) )
697 else if( aNodeName == wxT( "FINGER" ) )
699 else if( aNodeName == wxT( "OCTAGON" ) )
701 else if( aNodeName == wxT( "RECTANGLE" ) )
703 else if( aNodeName == wxT( "ROUNDED" ) )
705 else if( aNodeName == wxT( "SQUARE" ) )
707 else
708 wxASSERT( true );
709
710 switch( ShapeType )
711 {
713 Size = GetXmlAttributeIDLong( aNode, 0 );
715 break;
716
720
725 LeftLength = GetXmlAttributeIDLong( aNode, 1 );
727
731 if( aNode->GetChildren() )
732 {
733 if( aNode->GetChildren()->GetName() == wxT( "ORIENT" ) )
734 {
736 }
737 else
738 {
739 WARN_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
740 }
741
742 CheckNoNextNodes( aNode->GetChildren() );
743 }
745
747 Size = GetXmlAttributeIDLong( aNode, 0 );
748 break;
749 }
750}
751
752
754{
755 wxASSERT( aNode->GetName() == wxT( "PADREASSIGN" ) );
756
757 LayerID = GetXmlAttributeIDString( aNode, 0 );
758
759 XNODE* shapeNode = aNode->GetChildren();
760
761 if( CADSTAR_PAD_SHAPE::IsPadShape( shapeNode ) )
762 {
763 Shape.Parse( shapeNode, aContext );
764 HasShape = true;
765 }
766 else
767 {
768 wxString found = shapeNode ? shapeNode->GetName() : wxString( "(empty)" );
769 WARN_UNKNOWN_NODE_IO_ERROR( found, aNode->GetName() );
770 }
771
772 CheckNoNextNodes( shapeNode );
773}
774
775
777{
778 wxASSERT( aNode->GetName() == wxT( "PADCODE" ) );
779
780 ID = GetXmlAttributeIDString( aNode, 0 );
781 Name = GetXmlAttributeIDString( aNode, 1 );
782
783 XNODE* cNode = aNode->GetChildren();
784 wxString location = wxString::Format( wxT( "PADCODE -> %s" ), Name );
785
786 for( ; cNode; cNode = cNode->GetNext() )
787 {
788 wxString cNodeName = cNode->GetName();
789
790 if( CADSTAR_PAD_SHAPE::IsPadShape( cNode ) )
791 {
792 Shape.Parse( cNode, aContext );
793 }
794 else if( cNodeName == wxT( "CLEARANCE" ) )
795 {
797 }
798 else if( cNodeName == wxT( "RELIEFWIDTH" ) )
799 {
801 }
802 else if( cNodeName == wxT( "DRILL" ) )
803 {
805 XNODE* subNode = cNode->GetChildren();
806
807 for( ; subNode; subNode = subNode->GetNext() )
808 {
809 wxString subNodeName = subNode->GetName();
810
811 if( subNodeName == wxT( "NONPLATED" ) )
812 Plated = false;
813 else if( subNodeName == wxT( "OVERSIZE" ) )
814 DrillOversize = GetXmlAttributeIDLong( subNode, 0 );
815 else
816 WARN_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
817 }
818 }
819 else if( cNodeName == wxT( "DRILLLENGTH" ) )
820 {
821 SlotLength = GetXmlAttributeIDLong( cNode, 0 );
822 }
823 else if( cNodeName == wxT( "DRILLORIENTATION" ) )
824 {
826 }
827 else if( cNodeName == wxT( "DRILLXOFFSET" ) )
828 {
830 }
831 else if( cNodeName == wxT( "DRILLYOFFSET" ) )
832 {
834 }
835 else if( cNodeName == wxT( "PADREASSIGN" ) )
836 {
837 PADREASSIGN reassign;
838 reassign.Parse( cNode, aContext );
839
840 if( reassign.HasShape )
841 Reassigns.insert( std::make_pair( reassign.LayerID, reassign.Shape ) );
842 }
843 else
844 {
846 }
847 }
848}
849
850
852{
853 wxASSERT( aNode->GetName() == wxT( "VIAREASSIGN" ) );
854
855 LayerID = GetXmlAttributeIDString( aNode, 0 );
856
857 XNODE* shapeNode = aNode->GetChildren();
858
859 if( CADSTAR_PAD_SHAPE::IsPadShape( shapeNode ) )
860 {
861 Shape.Parse( shapeNode, aContext );
862 HasShape = true;
863 }
864 else
865 {
866 wxString found = shapeNode ? shapeNode->GetName() : wxString( "(empty)" );
867 WARN_UNKNOWN_NODE_IO_ERROR( found, aNode->GetName() );
868 }
869
870 CheckNoNextNodes( shapeNode );
871}
872
873
875{
876 wxASSERT( aNode->GetName() == wxT( "VIACODE" ) );
877
878 ID = GetXmlAttributeIDString( aNode, 0 );
879 Name = GetXmlAttributeIDString( aNode, 1 );
880
881 XNODE* cNode = aNode->GetChildren();
882 wxString location = wxString::Format( wxT( "VIACODE -> %s" ), Name );
883
884 for( ; cNode; cNode = cNode->GetNext() )
885 {
886 wxString cNodeName = cNode->GetName();
887
888 if( CADSTAR_PAD_SHAPE::IsPadShape( cNode ) )
889 {
890 Shape.Parse( cNode, aContext );
891 }
892 else if( cNodeName == wxT( "CLEARANCE" ) )
893 {
895 }
896 else if( cNodeName == wxT( "RELIEFWIDTH" ) )
897 {
899 }
900 else if( cNodeName == wxT( "DRILL" ) )
901 {
903 XNODE* subNode = cNode->GetChildren();
904
905 for( ; subNode; subNode = subNode->GetNext() )
906 {
907 wxString subNodeName = subNode->GetName();
908
909 if( subNodeName == wxT( "OVERSIZE" ) )
910 DrillOversize = GetXmlAttributeIDLong( subNode, 0 );
911 else
912 WARN_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
913 }
914 }
915 else if( cNodeName == wxT( "VIAREASSIGN" ) )
916 {
917 VIAREASSIGN reassign;
918 reassign.Parse( cNode, aContext );
919
920 if( reassign.HasShape )
921 Reassigns.insert( std::make_pair( reassign.LayerID, reassign.Shape ) );
922 }
923 else
924 {
926 }
927 }
928}
929
930
932{
933 wxASSERT( aNode->GetName() == wxT( "LAYERPAIR" ) );
934
935 ID = GetXmlAttributeIDString( aNode, 0 );
936 Name = GetXmlAttributeIDString( aNode, 1 );
937
940
941 wxString location = wxString::Format( wxT( "LAYERPAIR -> %s" ), Name );
942
943 if( aNode->GetChildren() )
944 {
945 if( aNode->GetChildren()->GetName() == wxT( "VIACODEREF" ) )
946 {
948 }
949 else
950 {
951 WARN_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), location );
952 }
953
954 CheckNoNextNodes( aNode->GetChildren() );
955 }
956}
957
958
960{
961 wxASSERT( aNode->GetName() == wxT( "SPCCLASSSPACE" ) );
962
965 LayerID = GetXmlAttributeIDString( aNode, 2 );
966 Spacing = GetXmlAttributeIDLong( aNode, 3 );
967}
968
969
971{
972 wxASSERT( aNode->GetName() == wxT( "TECHNOLOGY" ) );
973
974 XNODE* cNode = aNode->GetChildren();
975
976 for( ; cNode; cNode = cNode->GetNext() )
977 {
978 wxString cNodeName = cNode->GetName();
979
980 if( ParseSubNode( cNode, aContext ) ) //CADSTAR_ARCHIVE_PARSER::SETTINGS
981 {
982 }
983 else if( cNodeName == wxT( "MINROUTEWIDTH" ) )
984 {
986 }
987 else if( cNodeName == wxT( "MINNECKED" ) )
988 {
990 }
991 else if( cNodeName == wxT( "MINUNNECKED" ) )
992 {
994 }
995 else if( cNodeName == wxT( "MINMITER" ) )
996 {
997 MinMitre = GetXmlAttributeIDLong( cNode, 0 );
998 }
999 else if( cNodeName == wxT( "MAXMITER" ) )
1000 {
1001 MaxMitre = GetXmlAttributeIDLong( cNode, 0 );
1002 }
1003 else if( cNodeName == wxT( "MAXPHYSLAYER" ) )
1004 {
1006 }
1007 else if( cNodeName == wxT( "TRACKGRID" ) )
1008 {
1009 TrackGrid = GetXmlAttributeIDLong( cNode, 0 );
1010 }
1011 else if( cNodeName == wxT( "VIAGRID" ) )
1012 {
1013 ViaGrid = GetXmlAttributeIDLong( cNode, 0 );
1014 }
1015 else if( cNodeName == wxT( "BACKOFFJCTS" ) )
1016 {
1017 BackOffJunctions = true;
1018 }
1019 else if( cNodeName == wxT( "BCKOFFWIDCHANGE" ) )
1020 {
1021 BackOffWidthChange = true;
1022 }
1023 else
1024 {
1025 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TECHNOLOGY" ) );
1026 }
1027 }
1028}
1029
1030
1032 const wxString& aPadSideString )
1033{
1034 if( aPadSideString == wxT( "THRU" ) )
1036 else if( aPadSideString == wxT( "BOTTOM" ) )
1037 return PAD_SIDE::MAXIMUM;
1038 else if( aPadSideString == wxT( "TOP" ) )
1039 return PAD_SIDE::MINIMUM;
1040 else
1041 return PAD_SIDE::THROUGH_HOLE; // Assume through hole as default
1042}
1043
1044
1046{
1047 wxASSERT( aNode->GetName() == wxT( "COMPCOPPER" ) );
1048
1050 LayerID = GetXmlAttributeIDString( aNode, 1 );
1051
1052 XNODE* cNode = aNode->GetChildren();
1053 bool shapeIsInitialised = false; // Stop more than one Shape Object
1054 wxString location = wxT( "COMPCOPPER" );
1055
1056 if( !cNode )
1057 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1058
1059 for( ; cNode; cNode = cNode->GetNext() )
1060 {
1061 wxString cNodeName = cNode->GetName();
1062
1063 if( !shapeIsInitialised && Shape.IsShape( cNode ) )
1064 {
1065 Shape.Parse( cNode, aContext );
1066 shapeIsInitialised = true;
1067 }
1068 else if( cNodeName == wxT( "SWAPRULE" ) )
1069 {
1070 SwapRule = ParseSwapRule( cNode );
1071 }
1072 else if( cNodeName == wxT( "ASSOCPIN" ) )
1073 {
1074 wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
1075
1076 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1077 {
1078 if( !IsValidAttribute( xmlAttribute ) )
1079 continue;
1080
1081 long padId;
1082
1083 if( !xmlAttribute->GetValue().ToLong( &padId ) )
1084 THROW_PARSING_IO_ERROR( wxT( "ASSOCPIN" ), location );
1085
1086 AssociatedPadIDs.push_back( (PAD_ID) padId );
1087 }
1088
1089 CheckNoChildNodes( cNode );
1090 }
1091 else
1092 {
1094 }
1095 }
1096}
1097
1098
1100{
1101 wxASSERT( aNode->GetName() == wxT( "COMPAREA" ) );
1102
1103 ID = GetXmlAttributeIDString( aNode, 0 );
1104 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1105 LayerID = GetXmlAttributeIDString( aNode, 3 );
1106
1107 XNODE* cNode = aNode->GetChildren();
1108 bool shapeIsInitialised = false; // Stop more than one Shape Object
1109 wxString location = wxString::Format( wxT( "COMPAREA %s" ), ID );
1110
1111 if( !cNode )
1112 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1113
1114 for( ; cNode; cNode = cNode->GetNext() )
1115 {
1116 wxString cNodeName = cNode->GetName();
1117
1118 if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
1119 {
1120 Shape.Parse( cNode, aContext );
1121 shapeIsInitialised = true;
1122 }
1123 else if( cNodeName == wxT( "SWAPRULE" ) )
1124 {
1125 SwapRule = ParseSwapRule( cNode );
1126 }
1127 else if( cNodeName == wxT( "USAGE" ) )
1128 {
1129 wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
1130
1131 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1132 {
1133 if( !IsValidAttribute( xmlAttribute ) )
1134 continue;
1135
1136 if( xmlAttribute->GetValue() == wxT( "NO_TRACKS" ) )
1137 NoTracks = true;
1138 else if( xmlAttribute->GetValue() == wxT( "NO_VIAS" ) )
1139 NoVias = true;
1140 else
1141 WARN_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), location );
1142 }
1143
1144 CheckNoChildNodes( cNode );
1145 }
1146 else
1147 {
1149 }
1150 }
1151}
1152
1153
1155{
1156 wxASSERT( aNode->GetName() == wxT( "EXITS" ) );
1157
1158 wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
1159
1160 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1161 {
1162 if( !IsValidAttribute( xmlAttribute ) )
1163 continue;
1164
1165 if( xmlAttribute->GetValue() == wxT( "FREE" ) )
1166 FreeAngle = true;
1167 else if( xmlAttribute->GetValue() == wxT( "N" ) )
1168 North = true;
1169 else if( xmlAttribute->GetValue() == wxT( "S" ) )
1170 South = true;
1171 else if( xmlAttribute->GetValue() == wxT( "E" ) )
1172 East = true;
1173 else if( xmlAttribute->GetValue() == wxT( "W" ) )
1174 West = true;
1175 else if( xmlAttribute->GetValue() == wxT( "NE" ) )
1176 NorthEast = true;
1177 else if( xmlAttribute->GetValue() == wxT( "NW" ) )
1178 NorthWest = true;
1179 else if( xmlAttribute->GetValue() == wxT( "SE" ) )
1180 SouthEast = true;
1181 else if( xmlAttribute->GetValue() == wxT( "SW" ) )
1182 SouthWest = true;
1183 else
1184 WARN_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), wxT( "EXITS" ) );
1185 }
1186
1187 CheckNoChildNodes( aNode );
1188}
1189
1190
1192{
1193 wxASSERT( aNode->GetName() == wxT( "PAD" ) );
1194
1195 ID = GetXmlAttributeIDLong( aNode, 0 );
1196 PadCodeID = GetXmlAttributeIDString( aNode, 2 );
1197 Side = GetPadSide( GetXmlAttributeIDString( aNode, 3 ) );
1198
1199 XNODE* cNode = aNode->GetChildren();
1200 wxString location = wxString::Format( wxT( "PAD %ld" ), ID );
1201
1202 if( !cNode )
1203 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), location );
1204
1205 for( ; cNode; cNode = cNode->GetNext() )
1206 {
1207 wxString cNodeName = cNode->GetName();
1208
1209 if( cNodeName == wxT( "ORIENT" ) )
1210 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1211 else if( cNodeName == wxT( "FIRSTPAD" ) )
1212 FirstPad = true;
1213 else if( cNodeName == wxT( "EXITS" ) )
1214 Exits.Parse( cNode, aContext );
1215 else if( cNodeName == wxT( "PADIDENTIFIER" ) )
1216 Identifier = GetXmlAttributeIDString( cNode, 0 );
1217 else if( cNodeName == wxT( "PCBONLYPAD" ) )
1218 PCBonlyPad = true;
1219 else if( cNodeName == wxT( "PT" ) )
1220 Position.Parse( cNode, aContext );
1221 else
1223 }
1224}
1225
1226
1228{
1229 wxASSERT( aNode->GetName() == wxT( "DIMARROW" ) );
1230 bool arrowStyleInitialised = false;
1231 bool upperAngleInitialised = false;
1232 bool lowerAngleInitialised = false;
1233
1234 ArrowLength = GetXmlAttributeIDLong( aNode, 3 );
1235
1236 XNODE* cNode = aNode->GetChildren();
1237
1238
1239 for( ; cNode; cNode = cNode->GetNext() )
1240 {
1241 wxString cNodeName = cNode->GetName();
1242
1243 if( cNodeName == wxT( "ARROWSTYLE" ) )
1244 {
1245 wxString arrowStyleStr = GetXmlAttributeIDString( cNode, 0 );
1246 arrowStyleInitialised = true;
1247
1248 if( arrowStyleStr == wxT( "DIMENSION_ARROWOPEN" ) )
1250 else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLOSED" ) )
1252 else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLEAR" ) )
1254 else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLOSEDFILLED" ) )
1256 else
1257 WARN_UNKNOWN_PARAMETER_IO_ERROR( arrowStyleStr, cNodeName );
1258 }
1259 else if( cNodeName == wxT( "ARROWANGLEA" ) )
1260 {
1261 UpperAngle = GetXmlAttributeIDLong( cNode, 0 );
1262 upperAngleInitialised = true;
1263 }
1264 else if( cNodeName == wxT( "ARROWANGLEB" ) )
1265 {
1266 LowerAngle = GetXmlAttributeIDLong( cNode, 0 );
1267 lowerAngleInitialised = true;
1268 }
1269 else
1270 {
1271 WARN_UNKNOWN_PARAMETER_IO_ERROR( cNodeName, wxT( "DIMARROW" ) );
1272 }
1273 }
1274
1275 if( !arrowStyleInitialised )
1276 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWSTYLE" ), wxT( "DIMARROW" ) );
1277
1278 if( !upperAngleInitialised )
1279 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWANGLEA" ), wxT( "DIMARROW" ) );
1280
1281 if( !lowerAngleInitialised )
1282 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWANGLEB" ), wxT( "DIMARROW" ) );
1283}
1284
1285
1287 PARSER_CONTEXT* aContext )
1288{
1289 wxASSERT( aNode->GetName() == wxT( "DIMTEXT" ) );
1290
1291 TextGap = GetXmlAttributeIDLong( aNode, 1 );
1292 TextOffset = GetXmlAttributeIDLong( aNode, 2 );
1293
1294 XNODE* cNode = aNode->GetChildren();
1295
1296 if( !cNode )
1297 {
1298 WARN_UNKNOWN_NODE_IO_ERROR( wxT( "(empty)" ), wxT( "DIMTEXT" ) );
1299 return;
1300 }
1301
1302 if( cNode->GetName() != wxT( "TXTSTYLE" ) )
1303 {
1304 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "DIMTEXT" ) );
1305 return;
1306 }
1307
1308 wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
1309
1310 if( styleStr == wxT( "DIMENSION_INTERNAL" ) )
1312 else if( styleStr == wxT( "DIMENSION_EXTERNAL" ) )
1314 else
1315 WARN_UNKNOWN_PARAMETER_IO_ERROR( styleStr, wxT( "TXTSTYLE" ) );
1316
1317 CheckNoNextNodes( cNode );
1318}
1319
1320
1322 PARSER_CONTEXT* aContext )
1323{
1324 wxASSERT( aNode->GetName() == wxT( "EXTLINE" ) );
1325
1326 LineCodeID = GetXmlAttributeIDString( aNode, 0 );
1327 Overshoot = GetXmlAttributeIDLong( aNode, 3 );
1328 Offset = GetXmlAttributeIDLong( aNode, 4 );
1329
1330 XNODE* cNode = aNode->GetChildren();
1331 int noOfPoints = 0;
1332
1333 for( ; cNode; cNode = cNode->GetNext() )
1334 {
1335 wxString cNodeName = cNode->GetName();
1336
1337 if( noOfPoints < 2 && cNodeName == wxT( "PT" ) )
1338 {
1339 ++noOfPoints;
1340
1341 if( noOfPoints == 1 )
1342 Start.Parse( cNode, aContext );
1343 else
1344 End.Parse( cNode, aContext );
1345 }
1346 else if( cNodeName == wxT( "SUPPRESSFIRST" ) )
1347 {
1348 SuppressFirst = true;
1349 }
1350 else
1351 {
1352 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "EXTLINE" ) );
1353 }
1354 }
1355
1356 if( noOfPoints != 2 )
1357 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), wxT( "EXTLINE" ) );
1358}
1359
1360
1362{
1363 if( aNode->GetName() == wxT( "LEADERLINE" ) || aNode->GetName() == wxT( "LINEARLINE" )
1364 || aNode->GetName() == wxT( "ANGULARLINE" ) )
1365 {
1366 return true;
1367 }
1368 else
1369 {
1370 return false;
1371 }
1372}
1373
1374
1376{
1377 wxASSERT( IsLine( aNode ) );
1378
1379 if( aNode->GetName() == wxT( "LINEARLINE" ) )
1380 Type = TYPE::LINEARLINE;
1381 else if( aNode->GetName() == wxT( "LEADERLINE" ) )
1382 Type = TYPE::LEADERLINE;
1383 else if( aNode->GetName() == wxT( "ANGULARLINE" ) )
1384 Type = TYPE::ANGULARLINE;
1385 else
1386 wxASSERT_MSG( true, wxT( "Not a valid type. What happened to the node Name?" ) );
1387
1388 LineCodeID = GetXmlAttributeIDString( aNode, 0 );
1389
1390 if( Type == TYPE::LEADERLINE )
1391 {
1394 }
1395
1396 XNODE* cNode = aNode->GetChildren();
1397 int noOfPoints = 0;
1398 int requiredNoOfPoints = 2;
1399
1400 if( Type == TYPE::ANGULARLINE )
1401 requiredNoOfPoints = 3;
1402
1403 for( ; cNode; cNode = cNode->GetNext() )
1404 {
1405 wxString cNodeName = cNode->GetName();
1406
1407 if( cNodeName == wxT( "DIMLINETYPE" ) )
1408 {
1409 wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
1410
1411 if( styleStr == wxT( "DIMENSION_INTERNAL" ) )
1413 else if( styleStr == wxT( "DIMENSION_EXTERNAL" ) )
1415 else
1416 WARN_UNKNOWN_PARAMETER_IO_ERROR( styleStr, cNodeName );
1417 }
1418 else if( noOfPoints < requiredNoOfPoints && cNodeName == wxT( "PT" ) )
1419 {
1420 ++noOfPoints;
1421
1422 if( noOfPoints == 1 )
1423 Start.Parse( cNode, aContext );
1424 else if( noOfPoints == 2 )
1425 End.Parse( cNode, aContext );
1426 else
1427 Centre.Parse( cNode, aContext );
1428 }
1429 else if( Type == TYPE::LEADERLINE && cNodeName == wxT( "LEADERANG" ) )
1430 {
1431 LeaderAngle = GetXmlAttributeIDLong( cNode, 0 );
1432 }
1433 else
1434 {
1435 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1436 }
1437 }
1438
1439 if( noOfPoints != requiredNoOfPoints )
1440 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
1441}
1442
1443
1445{
1446 if( aNode->GetName() == wxT( "LINEARDIM" ) || aNode->GetName() == wxT( "LEADERDIM" )
1447 || aNode->GetName() == wxT( "ANGLEDIM" ) )
1448 {
1449 return true;
1450 }
1451 else
1452 {
1453 return false;
1454 }
1455}
1456
1457
1459{
1460 wxASSERT( IsDimension( aNode ) );
1461
1462 std::map<wxString, TYPE> typeMap = { { wxT( "LINEARDIM" ), TYPE::LINEARDIM },
1463 { wxT( "LEADERDIM" ), TYPE::LEADERDIM }, { wxT( "ANGLEDIM" ), TYPE::ANGLEDIM } };
1464
1465 //make sure aNode is valid TYPE
1466 wxASSERT_MSG( typeMap.find( aNode->GetName() ) != typeMap.end(),
1467 wxT( "Not a valid type. What happened to the node Name?" ) );
1468
1469 Type = typeMap[aNode->GetName()];
1470 LayerID = GetXmlAttributeIDString( aNode, 1 );
1471 wxString subTypeStr = GetXmlAttributeIDString( aNode, 2 );
1472
1473 std::map<wxString, SUBTYPE> subTypeMap = {
1474 { wxT( "DIMENSION_ORTHOGONAL" ), SUBTYPE::ORTHOGONAL },
1475 { wxT( "DIMENSION_DIRECT" ), SUBTYPE::DIRECT },
1476 { wxT( "DIMENSION_ANGLED" ), SUBTYPE::ANGLED },
1477 { wxT( "DIMENSION_DIAMETER" ), SUBTYPE::DIAMETER },
1478 { wxT( "DIMENSION_RADIUS" ), SUBTYPE::RADIUS },
1479 { wxT( "DIMENSION_ANGULAR" ), SUBTYPE::ANGULAR } };
1480
1481 if( subTypeMap.find( subTypeStr ) == subTypeMap.end() )
1482 {
1483 WARN_UNKNOWN_PARAMETER_IO_ERROR( subTypeStr, aNode->GetName() );
1485 }
1486 else
1487 {
1488 Subtype = subTypeMap[subTypeStr];
1489 }
1490 Precision = GetXmlAttributeIDLong( aNode, 3 );
1491
1492 XNODE* cNode = aNode->GetChildren();
1493
1494 bool idParsed = false;
1495 bool unitsParsed = false; //UNITS or ANGUNITS
1496 bool arrowParsed = false;
1497 bool textFormatParsed = false;
1498 bool extLineParsed = false;
1499 bool lineParsed = false;
1500 bool textParsed = false;
1501
1502 for( ; cNode; cNode = cNode->GetNext() )
1503 {
1504 wxString cNodeName = cNode->GetName();
1505
1506 if( !idParsed && cNodeName == wxT( "DIMREF" ) )
1507 {
1508 ID = GetXmlAttributeIDString( cNode, 0 );
1509 idParsed = true;
1510 }
1511 else if( !unitsParsed && cNodeName == wxT( "UNITS" ) )
1512 {
1513 LinearUnits = ParseUnits( cNode );
1514 unitsParsed = true;
1515 }
1516 else if( !unitsParsed && cNodeName == wxT( "ANGUNITS" ) )
1517 {
1518 AngularUnits = ParseAngunits( cNode );
1519 unitsParsed = true;
1520 }
1521 else if( !arrowParsed && cNodeName == wxT( "DIMARROW" ) )
1522 {
1523 Arrow.Parse( cNode, aContext );
1524 arrowParsed = true;
1525 }
1526 else if( !textFormatParsed && cNodeName == wxT( "DIMTEXT" ) )
1527 {
1528 TextParams.Parse( cNode, aContext );
1529 textFormatParsed = true;
1530 }
1531 else if( !extLineParsed && cNodeName == wxT( "EXTLINE" ) )
1532 {
1533 ExtensionLineParams.Parse( cNode, aContext );
1534 extLineParsed = true;
1535 }
1536 else if( !lineParsed && LINE::IsLine( cNode ) )
1537 {
1538 Line.Parse( cNode, aContext );
1539 lineParsed = true;
1540 }
1541 else if( !textParsed && cNodeName == wxT( "TEXT" ) )
1542 {
1543 // Do not parse the fields in dimension text (will be done when loading, if required)
1544 Text.Parse( cNode, aContext, false );
1545 textParsed = true;
1546 }
1547 else if( cNodeName == wxT( "FIX" ) )
1548 {
1549 Fixed = true;
1550 }
1551 else if( cNodeName == wxT( "GROUPREF" ) )
1552 {
1553 GroupID = GetXmlAttributeIDString( cNode, 0 );
1554 }
1555 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1556 {
1557 ReuseBlockRef.Parse( cNode, aContext );
1558 }
1559 else
1560 {
1561 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1562 }
1563 }
1564}
1565
1566
1568{
1569 wxASSERT( aNode->GetName() == wxT( "SYMDEF" ) );
1570
1571 ParseIdentifiers( aNode, aContext );
1572
1573 wxString rest;
1574
1575 if( ReferenceName.StartsWith( wxT( "JUMPERNF" ), &rest ) )
1577 else if( ReferenceName.StartsWith( wxT( "STARPOINTNF" ), &rest ) )
1579 else if( ReferenceName == wxT( "TESTPOINT" ) )
1581 else
1583
1584 XNODE* cNode = aNode->GetChildren();
1585
1586 for( ; cNode; cNode = cNode->GetNext() )
1587 {
1588 wxString cNodeName = cNode->GetName();
1589
1590 if( ParseSubNode( cNode, aContext ) )
1591 {
1592 continue;
1593 }
1594 else if( cNodeName == wxT( "SYMHEIGHT" ) )
1595 {
1596 SymHeight = GetXmlAttributeIDLong( cNode, 0 );
1597 }
1598 else if( cNodeName == wxT( "COMPCOPPER" ) )
1599 {
1600 COMPONENT_COPPER compcopper;
1601 compcopper.Parse( cNode, aContext );
1602 ComponentCoppers.push_back( compcopper );
1603 }
1604 else if( cNodeName == wxT( "COMPAREA" ) )
1605 {
1606 COMPONENT_AREA area;
1607 area.Parse( cNode, aContext );
1608 ComponentAreas.insert( std::make_pair( area.ID, area ) );
1609 }
1610 else if( cNodeName == wxT( "PAD" ) )
1611 {
1613 pad.Parse( cNode, aContext );
1614 ComponentPads.insert( std::make_pair( pad.ID, pad ) );
1615 }
1616 else if( cNodeName == wxT( "DIMENSIONS" ) )
1617 {
1618 XNODE* dimensionNode = cNode->GetChildren();
1619
1620 for( ; dimensionNode; dimensionNode = dimensionNode->GetNext() )
1621 {
1622 if( DIMENSION::IsDimension( dimensionNode ) )
1623 {
1624 DIMENSION dim;
1625 dim.Parse( dimensionNode, aContext );
1626 Dimensions.insert( std::make_pair( dim.ID, dim ) );
1627 }
1628 else
1629 {
1630 WARN_UNKNOWN_NODE_IO_ERROR( dimensionNode->GetName(), cNodeName );
1631 }
1632 }
1633 }
1634 else
1635 {
1636 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1637 }
1638 }
1639
1640 if( !Stub && ( Origin.x == UNDEFINED_VALUE || Origin.y == UNDEFINED_VALUE ) )
1641 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
1642}
1643
1644
1646{
1647 wxASSERT( aNode->GetName() == wxT( "LIBRARY" ) );
1648
1649 XNODE* cNode = aNode->GetChildren();
1650
1651 for( ; cNode; cNode = cNode->GetNext() )
1652 {
1653 wxString cNodeName = cNode->GetName();
1654
1655 if( cNodeName == wxT( "SYMDEF" ) )
1656 {
1657 SYMDEF_PCB symdef;
1658 symdef.Parse( cNode, aContext );
1659 ComponentDefinitions.insert( std::make_pair( symdef.ID, symdef ) );
1660 }
1661 else if( cNodeName == wxT( "HIERARCHY" ) )
1662 {
1663 // Ignore for now
1664 //
1665 // This node doesn't have any equivalent in KiCad so for now we ignore it. In
1666 // future, we could parse it in detail, to obtain the tree-structure of
1667 // footprints in a cadstar library
1668 }
1669 else
1670 {
1671 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1672 }
1673
1674 aContext->CheckPointCallback();
1675 }
1676}
1677
1678
1680{
1681 wxASSERT( aNode->GetName() == wxT( "BOARD" ) );
1682
1683 ID = GetXmlAttributeIDString( aNode, 0 );
1684 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1685
1686 XNODE* cNode = aNode->GetChildren();
1687 bool shapeIsInitialised = false; // Stop more than one Shape Object
1688 wxString location = wxString::Format( wxT( "BOARD %s" ), ID );
1689
1690 if( !cNode )
1691 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1692
1693 for( ; cNode; cNode = cNode->GetNext() )
1694 {
1695 wxString cNodeName = cNode->GetName();
1696
1697 if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
1698 {
1699 Shape.Parse( cNode, aContext );
1700 shapeIsInitialised = true;
1701 }
1702 else if( cNodeName == wxT( "ATTR" ) )
1703 {
1704 ATTRIBUTE_VALUE attr;
1705 attr.Parse( cNode, aContext );
1706 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1707 }
1708 else if( cNodeName == wxT( "FIX" ) )
1709 {
1710 Fixed = true;
1711 }
1712 else if( cNodeName == wxT( "GROUPREF" ) )
1713 {
1714 GroupID = GetXmlAttributeIDString( cNode, 0 );
1715 }
1716 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1717 {
1718 ReuseBlockRef.Parse( cNode, aContext );
1719 }
1720 else
1721 {
1723 }
1724 }
1725}
1726
1727
1729{
1730 wxASSERT( aNode->GetName() == wxT( "AREA" ) );
1731
1732 ID = GetXmlAttributeIDString( aNode, 0 );
1733 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1734 Name = GetXmlAttributeIDString( aNode, 2 );
1735 LayerID = GetXmlAttributeIDString( aNode, 4 );
1736
1737 XNODE* cNode = aNode->GetChildren();
1738 bool shapeIsInitialised = false; // Stop more than one Shape Object
1739 wxString location = wxString::Format( wxT( "AREA %s" ), ID );
1740
1741 if( !cNode )
1742 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1743
1744 for( ; cNode; cNode = cNode->GetNext() )
1745 {
1746 wxString cNodeName = cNode->GetName();
1747
1748 if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
1749 {
1750 Shape.Parse( cNode, aContext );
1751 shapeIsInitialised = true;
1752 }
1753 else if( cNodeName == wxT( "FIX" ) )
1754 {
1755 Fixed = true;
1756 }
1757 else if( cNodeName == wxT( "USAGE" ) )
1758 {
1759 wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
1760
1761 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1762 {
1763 if( !IsValidAttribute( xmlAttribute ) )
1764 continue;
1765
1766 if( xmlAttribute->GetValue() == wxT( "PLACEMENT" ) )
1767 Placement = true;
1768 else if( xmlAttribute->GetValue() == wxT( "ROUTING" ) )
1769 Routing = true;
1770 else if( xmlAttribute->GetValue() == wxT( "KEEPOUT" ) )
1771 Keepout = true;
1772 else if( xmlAttribute->GetValue() == wxT( "NO_TRACKS" ) )
1773 NoTracks = true;
1774 else if( xmlAttribute->GetValue() == wxT( "NO_VIAS" ) )
1775 NoVias = true;
1776 else
1777 WARN_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), location );
1778 }
1779
1780 CheckNoChildNodes( cNode );
1781 }
1782 else if( cNodeName == wxT( "AREAHEIGHT" ) )
1783 {
1784 AreaHeight = GetXmlAttributeIDLong( cNode, 0 );
1785 }
1786 else if( cNodeName == wxT( "GROUPREF" ) )
1787 {
1788 GroupID = GetXmlAttributeIDString( cNode, 0 );
1789 }
1790 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1791 {
1792 ReuseBlockRef.Parse( cNode, aContext );
1793 }
1794 else if( cNodeName == wxT( "ATTR" ) )
1795 {
1796 ATTRIBUTE_VALUE attr;
1797 attr.Parse( cNode, aContext );
1798 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1799 }
1800 else
1801 {
1803 }
1804 }
1805}
1806
1807
1809{
1810 wxASSERT( aNode->GetName() == wxT( "PINATTR" ) );
1811
1812 Pin = GetXmlAttributeIDLong( aNode, 0 );
1813
1814 XNODE* cNode = aNode->GetChildren();
1815
1816 for( ; cNode; cNode = cNode->GetNext() )
1817 {
1818 wxString cNodeName = cNode->GetName();
1819
1820 if( cNodeName == wxT( "ATTR" ) )
1821 {
1822 ATTRIBUTE_VALUE attrVal;
1823 attrVal.Parse( cNode, aContext );
1824 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
1825 }
1826 else if( cNodeName == wxT( "TESTLAND" ) )
1827 {
1829 }
1830 else
1831 {
1832 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1833 }
1834 }
1835}
1836
1837
1839{
1840 wxASSERT( aNode->GetName() == wxT( "PADEXCEPTION" ) );
1841
1842 ID = GetXmlAttributeIDLong( aNode, 0 );
1843
1844 XNODE* cNode = aNode->GetChildren();
1845
1846 for( ; cNode; cNode = cNode->GetNext() )
1847 {
1848 wxString cNodeName = cNode->GetName();
1849
1850 if( cNodeName == wxT( "PADCODEREF" ) )
1851 {
1852 PadCode = GetXmlAttributeIDString( cNode, 0 );
1853 }
1854 else if( cNodeName == wxT( "EXITS" ) )
1855 {
1856 OverrideExits = true;
1857 Exits.Parse( cNode, aContext );
1858 }
1859 else if( cNodeName == wxT( "SIDE" ) )
1860 {
1861 OverrideSide = true;
1862 Side = GetPadSide( GetXmlAttributeIDString( cNode, 0 ) );
1863 }
1864 else if( cNodeName == wxT( "ORIENT" ) )
1865 {
1866 OverrideOrientation = true;
1867 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1868 }
1869 else
1870 {
1871 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1872 }
1873 }
1874}
1875
1876
1878{
1879 wxASSERT( aNode->GetName() == wxT( "COMP" ) );
1880
1881 ID = GetXmlAttributeIDString( aNode, 0 );
1882 Name = GetXmlAttributeIDString( aNode, 1 );
1883 PartID = GetXmlAttributeIDString( aNode, 2 );
1884 SymdefID = GetXmlAttributeIDString( aNode, 3 );
1885
1886 XNODE* cNode = aNode->GetChildren();
1887 bool originParsed = false;
1888
1889 for( ; cNode; cNode = cNode->GetNext() )
1890 {
1891 wxString cNodeName = cNode->GetName();
1892
1893 if( !originParsed && cNodeName == wxT( "PT" ) )
1894 {
1895 Origin.Parse( cNode, aContext );
1896 originParsed = true;
1897 }
1898 else if( cNodeName == wxT( "GROUPREF" ) )
1899 {
1900 GroupID = GetXmlAttributeIDString( cNode, 0 );
1901 }
1902 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1903 {
1904 ReuseBlockRef.Parse( cNode, aContext );
1905 }
1906 else if( cNodeName == wxT( "TESTPOINT" ) )
1907 {
1908 TestPoint = true;
1909 }
1910 else if( cNodeName == wxT( "FIX" ) )
1911 {
1912 Fixed = true;
1913 }
1914 else if( cNodeName == wxT( "MIRROR" ) )
1915 {
1916 Mirror = true;
1917 }
1918 else if( cNodeName == wxT( "READABILITY" ) )
1919 {
1920 Readability = ParseReadability( cNode );
1921 }
1922 else if( cNodeName == wxT( "ORIENT" ) )
1923 {
1924 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1925 }
1926 else if( cNodeName == wxT( "VCOMPMASTER" ) )
1927 {
1929 VariantID = GetXmlAttributeIDString( cNode, 1 );
1930 }
1931 else if( cNodeName == wxT( "TEXTLOC" ) )
1932 {
1933 TEXT_LOCATION textloc;
1934 textloc.Parse( cNode, aContext );
1935 TextLocations.insert( std::make_pair( textloc.AttributeID, textloc ) );
1936 }
1937 else if( cNodeName == wxT( "ATTR" ) )
1938 {
1939 ATTRIBUTE_VALUE attrVal;
1940 attrVal.Parse( cNode, aContext );
1941 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
1942 }
1943 else if( cNodeName == wxT( "PINATTR" ) )
1944 {
1945 PIN_ATTRIBUTE pinAttr;
1946 pinAttr.Parse( cNode, aContext );
1947 PinAttributes.insert( std::make_pair( pinAttr.Pin, pinAttr ) );
1948 }
1949 else if( cNodeName == wxT( "COMPPINLABEL" ) )
1950 {
1952 wxString pinLabel = GetXmlAttributeIDString( cNode, 1 );
1953 PinLabels.insert( std::make_pair( pinID, pinLabel ) );
1954 }
1955 else if( cNodeName == wxT( "PADEXCEPTION" ) )
1956 {
1957 PADEXCEPTION padExcept;
1958 padExcept.Parse( cNode, aContext );
1959 PadExceptions.insert( std::make_pair( padExcept.ID, padExcept ) );
1960 }
1961 else
1962 {
1963 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1964 }
1965 }
1966
1967 if( !originParsed )
1968 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
1969}
1970
1971
1973 XNODE* aNode )
1974{
1975 wxASSERT( aNode->GetName() == wxT( "TESTLAND" ) );
1976
1977 wxString side = GetXmlAttributeIDString( aNode, 0 );
1978
1979 if( side == wxT( "MIN_SIDE" ) )
1980 return TESTLAND_SIDE::MIN;
1981 else if( side == wxT( "MAX_SIDE" ) )
1982 return TESTLAND_SIDE::MAX;
1983 else if( side == wxT( "BOTH_SIDES" ) )
1984 return TESTLAND_SIDE::BOTH;
1985 else
1986 WARN_UNKNOWN_PARAMETER_IO_ERROR( side, aNode->GetName() );
1987
1988 return TESTLAND_SIDE::NONE;
1989}
1990
1991
1993{
1994 wxASSERT( aNode->GetName() == wxT( "TRUNK" ) );
1995
1996 ID = GetXmlAttributeIDString( aNode, 0 );
1997 Definition = GetXmlAttributeIDString( aNode, 1 );
1998}
1999
2000
2002{
2003 wxASSERT( aNode->GetName() == wxT( "PIN" ) );
2004
2005 ID = GetXmlAttributeIDString( aNode, 0 );
2007 PadID = GetXmlAttributeIDLong( aNode, 2 );
2008 CheckNoChildNodes( aNode );
2009}
2010
2011
2013 PARSER_CONTEXT* aContext )
2014{
2015 ParseIdentifiers( aNode, aContext );
2016 XNODE* cNode = aNode->GetChildren();
2017
2018 for( ; cNode; cNode = cNode->GetNext() )
2019 {
2020 if( ParseSubNode( cNode, aContext ) )
2021 continue;
2022 else if( cNode->GetName() == wxT( "TRUNKREF" ) )
2023 TrunkID = GetXmlAttributeIDString( cNode, 0 );
2024 else
2025 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2026 }
2027}
2028
2029
2031{
2032 wxASSERT( aNode->GetName() == wxT( "VIA" ) );
2033
2034 ID = GetXmlAttributeIDString( aNode, 0 );
2035 ViaCodeID = GetXmlAttributeIDString( aNode, 1 );
2037
2038 XNODE* cNode = aNode->GetChildren();
2039
2040 for( ; cNode; cNode = cNode->GetNext() )
2041 {
2042 wxString cNodeName = cNode->GetName();
2043
2044 if( cNodeName == wxT( "PT" ) )
2045 Location.Parse( cNode, aContext );
2046 else if( cNodeName == wxT( "FIX" ) )
2047 Fixed = true;
2048 else if( cNodeName == wxT( "GROUPREF" ) )
2049 GroupID = GetXmlAttributeIDString( cNode, 0 );
2050 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2051 ReuseBlockRef.Parse( cNode, aContext );
2052 else if( cNodeName == wxT( "TESTLAND" ) )
2054 else if( cNode->GetName() == wxT( "TRUNKREF" ) )
2055 TrunkID = GetXmlAttributeIDString( cNode, 0 );
2056 else
2057 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2058 }
2059}
2060
2061
2063 PARSER_CONTEXT* aContext )
2064{
2065 wxASSERT( aNode->GetName() == wxT( "COPTERM" ) );
2066
2067 ID = GetXmlAttributeIDString( aNode, 0 );
2068 CopperID = GetXmlAttributeIDString( aNode, 1 );
2070}
2071
2072
2074 PARSER_CONTEXT* aContext )
2075{
2076 XNODE* prevNode = aNode;
2077 XNODE* nextNode = aNode->GetNext();
2078 bool vertexParsed = false;
2079
2080 if( aNode->GetName() == wxT( "ROUTEWIDTH" ) )
2081 {
2082 RouteWidth = GetXmlAttributeIDLong( aNode, 0 );
2083 }
2084 else
2085 {
2086 // CADSTAR Revision 7 routes may omit ROUTEWIDTH and start directly with the vertex; the
2087 // width is derived later from the connection's route code.
2088 wxASSERT( VERTEX::IsVertex( aNode ) );
2089 RouteWidthIsExplicit = false;
2090 Vertex.Parse( aNode, aContext );
2091 vertexParsed = true;
2092 }
2093
2094 for( ; nextNode; nextNode = nextNode->GetNext() )
2095 {
2096 if( nextNode->GetName() == wxT( "FIX" ) )
2097 {
2098 Fixed = true;
2099 }
2100 else if( nextNode->GetName() == wxT( "TDROPATSTART" ) )
2101 {
2102 TeardropAtStart = true;
2104 }
2105 else if( nextNode->GetName() == wxT( "TDROPATEND" ) )
2106 {
2107 TeardropAtEnd = true;
2109 }
2110 else if( VERTEX::IsVertex( nextNode ) )
2111 {
2112 // A ROUTEWIDTH record holds a single vertex. Encountering another one (with no
2113 // intervening ROUTEWIDTH) marks the start of the next Revision 7 vertex record.
2114 if( vertexParsed )
2115 return prevNode;
2116
2117 Vertex.Parse( nextNode, aContext );
2118 vertexParsed = true;
2119 }
2120 else if( nextNode->GetName() == wxT( "ROUTEWIDTH" ) )
2121 {
2122 return prevNode;
2123 }
2124 else
2125 {
2126 WARN_UNKNOWN_NODE_IO_ERROR( nextNode->GetName(), wxT( "ROUTE" ) );
2127 }
2128
2129 prevNode = nextNode;
2130 }
2131
2132 return prevNode;
2133}
2134
2135
2137{
2138 wxASSERT( aNode->GetName() == wxT( "ROUTE" ) );
2139
2140 LayerID = GetXmlAttributeIDString( aNode, 0 );
2141
2142 //Parse child nodes
2143 XNODE* cNode = aNode->GetChildren();
2144 bool startPointParsed = false;
2145
2146 for( ; cNode; cNode = cNode->GetNext() )
2147 {
2148 wxString cNodeName = cNode->GetName();
2149
2150 if( !startPointParsed && cNodeName == wxT( "PT" ) )
2151 {
2152 startPointParsed = true;
2153 StartPoint.Parse( cNode, aContext );
2154 }
2155 else if( cNodeName == wxT( "ROUTEWIDTH" ) || VERTEX::IsVertex( cNode ) )
2156 {
2157 // A route vertex normally starts with ROUTEWIDTH, but CADSTAR Revision 7 files may
2158 // omit it and start directly with the vertex; ROUTE_VERTEX::Parse handles both and
2159 // consumes any trailing FIX/teardrop metadata, returning the last node it consumed.
2160 ROUTE_VERTEX rtVert;
2161 cNode = rtVert.Parse( cNode, aContext );
2162 RouteVertices.push_back( rtVert );
2163
2164 assert( cNode != nullptr );
2165 }
2166 else
2167 {
2168 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "ROUTE" ) );
2169 }
2170 }
2171}
2172
2173
2175 PARSER_CONTEXT* aContext )
2176{
2177 ParseIdentifiers( aNode, aContext );
2178
2179 //Parse child nodes
2180 XNODE* cNode = aNode->GetChildren();
2181 bool routeParsed = false; //assume only one route per connection
2182
2183 for( ; cNode; cNode = cNode->GetNext() )
2184 {
2185 wxString cNodeName = cNode->GetName();
2186
2187 if( ParseSubNode( cNode, aContext ) )
2188 {
2189 continue;
2190 }
2191 else if( !Unrouted && !routeParsed && cNodeName == wxT( "ROUTE" ) )
2192 {
2193 Route.Parse( cNode, aContext );
2194 routeParsed = true;
2195 }
2196 else if( !routeParsed && cNodeName == wxT( "UNROUTE" ) )
2197 {
2198 Unrouted = true;
2200 }
2201 else if( cNode->GetName() == wxT( "TRUNKREF" ) )
2202 {
2203 TrunkID = GetXmlAttributeIDString( cNode, 0 );
2204 }
2205 else
2206 {
2207 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "CONN" ) );
2208 }
2209 }
2210}
2211
2212
2214{
2215 ParseIdentifiers( aNode, aContext );
2216
2217 //Parse child nodes
2218 XNODE* cNode = aNode->GetChildren();
2219
2220 for( ; cNode; cNode = cNode->GetNext() )
2221 {
2222 wxString cNodeName = cNode->GetName();
2223
2224 if( cNodeName == wxT( "JPT" ) )
2225 {
2226 JUNCTION_PCB jpt;
2227 jpt.Parse( cNode, aContext );
2228 Junctions.insert( std::make_pair( jpt.ID, jpt ) );
2229 }
2230 else if( ParseSubNode( cNode, aContext ) )
2231 {
2232 continue;
2233 }
2234 else if( cNodeName == wxT( "PIN" ) )
2235 {
2236 PIN pin;
2237 pin.Parse( cNode, aContext );
2238 Pins.insert( std::make_pair( pin.ID, pin ) );
2239 }
2240 else if( cNodeName == wxT( "VIA" ) )
2241 {
2242 VIA via;
2243 via.Parse( cNode, aContext );
2244 Vias.insert( std::make_pair( via.ID, via ) );
2245 }
2246 else if( cNodeName == wxT( "COPTERM" ) )
2247 {
2248 COPPER_TERMINAL cterm;
2249 cterm.Parse( cNode, aContext );
2250 CopperTerminals.insert( std::make_pair( cterm.ID, cterm ) );
2251 }
2252 else if( cNodeName == wxT( "CONN" ) )
2253 {
2254 CONNECTION_PCB conn;
2255 conn.Parse( cNode, aContext );
2256 Connections.push_back( conn );
2257 }
2258 else
2259 {
2260 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "NET" ) );
2261 }
2262 }
2263}
2264
2265
2267{
2268 wxASSERT( aNode->GetName() == wxT( "POURING" ) );
2269
2273 SliverWidth = GetXmlAttributeIDLong( aNode, 3 );
2277
2278 wxString MinIsolCopStr = GetXmlAttributeIDString( aNode, 7 );
2279
2280 if( MinIsolCopStr == wxT( "NONE" ) )
2282 else
2284
2285 wxString MinDisjCopStr = GetXmlAttributeIDString( aNode, 8 );
2286
2287 if( MinDisjCopStr == wxT( "NONE" ) )
2289 else
2291
2292 XNODE* cNode = aNode->GetChildren();
2293
2294 for( ; cNode; cNode = cNode->GetNext() )
2295 {
2296 wxString cNodeName = cNode->GetName();
2297
2298 if( cNodeName == wxT( "NOPINRELIEF" ) )
2299 {
2300 ThermalReliefOnPads = false;
2301 }
2302 else if( cNodeName == wxT( "NOVIARELIEF" ) )
2303 {
2304 ThermalReliefOnVias = false;
2305 }
2306 else if( cNodeName == wxT( "IGNORETRN" ) )
2307 {
2308 AllowInNoRouting = true;
2309 }
2310 else if( cNodeName == wxT( "BOXPINS" ) )
2311 {
2312 BoxIsolatedPins = true;
2313 }
2314 else if( cNodeName == wxT( "REGENERATE" ) )
2315 {
2316 AutomaticRepour = true;
2317 }
2318 else if( cNodeName == wxT( "AUTOROUTETARGET" ) )
2319 {
2320 TargetForAutorouting = true;
2321 }
2322 else if( cNodeName == wxT( "THERMALCUTOUT" ) )
2323 {
2325 }
2326 else if( cNodeName == wxT( "FILLED" ) )
2327 {
2329 }
2330 else if( cNodeName == wxT( "HATCHCODEREF" ) )
2331 {
2334 }
2335 else
2336 {
2337 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "POURING" ) );
2338 }
2339 }
2340}
2341
2342
2344{
2345 wxASSERT( aNode->GetName() == wxT( "TEMPLATE" ) );
2346
2347 ID = GetXmlAttributeIDString( aNode, 0 );
2348 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
2349 Name = GetXmlAttributeIDString( aNode, 2 );
2350 NetID = GetXmlAttributeIDString( aNode, 3 );
2351 LayerID = GetXmlAttributeIDString( aNode, 4 );
2352
2353 XNODE* cNode = aNode->GetChildren();
2354 bool shapeParsed = false;
2355 bool pouringParsed = false;
2356
2357 for( ; cNode; cNode = cNode->GetNext() )
2358 {
2359 wxString cNodeName = cNode->GetName();
2360
2361 if( !shapeParsed && SHAPE::IsShape( cNode ) )
2362 {
2363 Shape.Parse( cNode, aContext );
2364 shapeParsed = true;
2365 }
2366 else if( !pouringParsed && cNodeName == wxT( "POURING" ) )
2367 {
2368 Pouring.Parse( cNode, aContext );
2369 pouringParsed = true;
2370 }
2371 else if( cNodeName == wxT( "FIX" ) )
2372 {
2373 Fixed = true;
2374 }
2375 else if( cNodeName == wxT( "GROUPREF" ) )
2376 {
2377 GroupID = GetXmlAttributeIDString( cNode, 0 );
2378 }
2379 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2380 {
2381 ReuseBlockRef.Parse( cNode, aContext );
2382 }
2383 else if( cNodeName == wxT( "ATTR" ) )
2384 {
2385 ATTRIBUTE_VALUE attr;
2386 attr.Parse( cNode, aContext );
2387 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2388 }
2389 else
2390 {
2391 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEMPLATE" ) );
2392 }
2393 }
2394}
2395
2396
2398 PARSER_CONTEXT* aContext )
2399{
2400 wxASSERT( aNode->GetName() == wxT( "TERM" ) );
2401
2402 ID = GetXmlAttributeIDLong( aNode, 0 );
2403
2404 XNODE* cNode = aNode->GetChildren();
2405 bool locationParsed = false;
2406
2407 for( ; cNode; cNode = cNode->GetNext() )
2408 {
2409 wxString cNodeName = cNode->GetName();
2410
2411 if( !locationParsed && cNodeName == wxT( "PT" ) )
2412 {
2413 Location.Parse( cNode, aContext );
2414 locationParsed = true;
2415 }
2416 else if( cNodeName == wxT( "FIX" ) )
2417 {
2418 Fixed = true;
2419 }
2420 else
2421 {
2422 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2423 }
2424 }
2425}
2426
2427
2429{
2430 wxASSERT( aNode->GetName() == wxT( "NETREF" ) );
2431
2432 NetID = GetXmlAttributeIDString( aNode, 0 );
2433
2434 XNODE* cNode = aNode->GetChildren();
2435
2436 for( ; cNode; cNode = cNode->GetNext() )
2437 {
2438 wxString cNodeName = cNode->GetName();
2439
2440 if( cNodeName == wxT( "TERM" ) )
2441 {
2442 COPPER_TERM term;
2443 term.Parse( cNode, aContext );
2444 CopperTerminals.insert( std::make_pair( term.ID, term ) );
2445 }
2446 else if( cNodeName == wxT( "FIX" ) )
2447 {
2448 Fixed = true;
2449 }
2450 else
2451 {
2452 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "NETREF" ) );
2453 }
2454 }
2455}
2456
2457
2459{
2460 wxASSERT( aNode->GetName() == wxT( "COPPER" ) );
2461
2462 ID = GetXmlAttributeIDString( aNode, 0 );
2464 LayerID = GetXmlAttributeIDString( aNode, 2 );
2465
2466 XNODE* cNode = aNode->GetChildren();
2467 bool shapeParsed = false;
2468 bool netRefParsed = false;
2469
2470 for( ; cNode; cNode = cNode->GetNext() )
2471 {
2472 wxString cNodeName = cNode->GetName();
2473
2474 if( !shapeParsed && SHAPE::IsShape( cNode ) )
2475 {
2476 Shape.Parse( cNode, aContext );
2477 shapeParsed = true;
2478 }
2479 else if( !netRefParsed && cNodeName == wxT( "NETREF" ) )
2480 {
2481 NetRef.Parse( cNode, aContext );
2482 netRefParsed = true;
2483 }
2484 else if( cNodeName == wxT( "FIX" ) )
2485 {
2486 Fixed = true;
2487 }
2488 else if( cNodeName == wxT( "GROUPREF" ) )
2489 {
2490 GroupID = GetXmlAttributeIDString( cNode, 0 );
2491 }
2492 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2493 {
2494 ReuseBlockRef.Parse( cNode, aContext );
2495 }
2496 else if( cNodeName == wxT( "POURED" ) )
2497 {
2499 }
2500 else if( cNodeName == wxT( "ATTR" ) )
2501 {
2502 ATTRIBUTE_VALUE attr;
2503 attr.Parse( cNode, aContext );
2504 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2505 }
2506 else
2507 {
2508 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEMPLATE" ) );
2509 }
2510 }
2511}
2512
2513
2515{
2516 wxASSERT( aNode->GetName() == wxT( "DRILLTABLE" ) );
2517
2518 ID = GetXmlAttributeIDString( aNode, 0 );
2519 LayerID = GetXmlAttributeIDString( aNode, 1 );
2520
2521 XNODE* cNode = aNode->GetChildren();
2522 bool positionParsed = false;
2523
2524 for( ; cNode; cNode = cNode->GetNext() )
2525 {
2526 wxString cNodeName = cNode->GetName();
2527
2528 if( !positionParsed && cNodeName == wxT( "PT" ) )
2529 {
2530 Position.Parse( cNode, aContext );
2531 positionParsed = true;
2532 }
2533 else if( cNodeName == wxT( "ORIENT" ) )
2534 {
2535 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
2536 }
2537 else if( cNodeName == wxT( "MIRROR" ) )
2538 {
2539 Mirror = true;
2540 }
2541 else if( cNodeName == wxT( "FIX" ) )
2542 {
2543 Fixed = true;
2544 }
2545 else if( cNodeName == wxT( "READABILITY" ) )
2546 {
2547 Readability = ParseReadability( cNode );
2548 }
2549 else if( cNodeName == wxT( "GROUPREF" ) )
2550 {
2551 GroupID = GetXmlAttributeIDString( cNode, 0 );
2552 }
2553 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2554 {
2555 ReuseBlockRef.Parse( cNode, aContext );
2556 }
2557 else
2558 {
2559 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2560 }
2561 }
2562}
2563
2564
2566{
2567 wxASSERT( aNode->GetName() == wxT( "LAYOUT" ) );
2568
2569 XNODE* cNode = aNode->GetChildren();
2570 bool netSynchParsed = false;
2571 bool dimensionsParsed = false;
2572
2573 for( ; cNode; cNode = cNode->GetNext() )
2574 {
2575 wxString cNodeName = cNode->GetName();
2576
2577 if( !netSynchParsed && cNodeName == wxT( "NETSYNCH" ) )
2578 {
2579 std::map<wxString, NETSYNCH> netSynchMap = { { wxT( "WARNING" ), NETSYNCH::WARNING },
2580 { wxT( "FULL" ), NETSYNCH::FULL } };
2581
2582 wxString nsString = GetXmlAttributeIDString( cNode, 0 );
2583
2584 if( netSynchMap.find( nsString ) == netSynchMap.end() )
2585 {
2586 WARN_UNKNOWN_PARAMETER_IO_ERROR( nsString, aNode->GetName() );
2588 }
2589 else
2590 {
2591 NetSynch = netSynchMap[nsString];
2592 }
2593 netSynchParsed = true;
2594 }
2595 else if( cNodeName == wxT( "GROUP" ) )
2596 {
2597 GROUP group;
2598 group.Parse( cNode, aContext );
2599 Groups.insert( std::make_pair( group.ID, group ) );
2600 }
2601 else if( cNodeName == wxT( "REUSEBLOCK" ) )
2602 {
2603 REUSEBLOCK reuseblock;
2604 reuseblock.Parse( cNode, aContext );
2605 ReuseBlocks.insert( std::make_pair( reuseblock.ID, reuseblock ) );
2606 }
2607 else if( cNodeName == wxT( "BOARD" ) )
2608 {
2609 CADSTAR_BOARD board;
2610 board.Parse( cNode, aContext );
2611 Boards.insert( std::make_pair( board.ID, board ) );
2612 }
2613 else if( cNodeName == wxT( "FIGURE" ) )
2614 {
2615 FIGURE figure;
2616 figure.Parse( cNode, aContext );
2617 Figures.insert( std::make_pair( figure.ID, figure ) );
2618 }
2619 else if( cNodeName == wxT( "AREA" ) )
2620 {
2621 AREA area;
2622 area.Parse( cNode, aContext );
2623 Areas.insert( std::make_pair( area.ID, area ) );
2624 }
2625 else if( cNodeName == wxT( "COMP" ) )
2626 {
2628 comp.Parse( cNode, aContext );
2629 Components.insert( std::make_pair( comp.ID, comp ) );
2630 }
2631 else if( cNodeName == wxT( "TRUNK" ) )
2632 {
2633 TRUNK trunk;
2634 trunk.Parse( cNode, aContext );
2635 Trunks.insert( std::make_pair( trunk.ID, trunk ) );
2636 }
2637 else if( cNodeName == wxT( "NET" ) )
2638 {
2639 NET_PCB net;
2640 net.Parse( cNode, aContext );
2641 Nets.insert( std::make_pair( net.ID, net ) );
2642 }
2643 else if( cNodeName == wxT( "TEMPLATE" ) )
2644 {
2645 TEMPLATE temp;
2646 temp.Parse( cNode, aContext );
2647 Templates.insert( std::make_pair( temp.ID, temp ) );
2648 }
2649 else if( cNodeName == wxT( "COPPER" ) )
2650 {
2651 COPPER copper;
2652 copper.Parse( cNode, aContext );
2653 Coppers.insert( std::make_pair( copper.ID, copper ) );
2654 }
2655 else if( cNodeName == wxT( "TEXT" ) )
2656 {
2657 TEXT txt;
2658 txt.Parse( cNode, aContext );
2659 Texts.insert( std::make_pair( txt.ID, txt ) );
2660 }
2661 else if( cNodeName == wxT( "DOCSYMBOL" ) )
2662 {
2663 DOCUMENTATION_SYMBOL docsym;
2664 docsym.Parse( cNode, aContext );
2665 DocumentationSymbols.insert( std::make_pair( docsym.ID, docsym ) );
2666 }
2667 else if( !dimensionsParsed && cNodeName == wxT( "DIMENSIONS" ) )
2668 {
2669 XNODE* dimensionNode = cNode->GetChildren();
2670
2671 for( ; dimensionNode; dimensionNode = dimensionNode->GetNext() )
2672 {
2673 if( DIMENSION::IsDimension( dimensionNode ) )
2674 {
2675 DIMENSION dim;
2676 dim.Parse( dimensionNode, aContext );
2677 Dimensions.insert( std::make_pair( dim.ID, dim ) );
2678 }
2679 else
2680 {
2681 WARN_UNKNOWN_NODE_IO_ERROR( dimensionNode->GetName(), cNodeName );
2682 }
2683 }
2684
2685 dimensionsParsed = true;
2686 }
2687 else if( cNodeName == wxT( "DRILLTABLE" ) )
2688 {
2689 DRILL_TABLE drilltable;
2690 drilltable.Parse( cNode, aContext );
2691 DrillTables.insert( std::make_pair( drilltable.ID, drilltable ) );
2692 }
2693 else if( cNodeName == wxT( "VHIERARCHY" ) )
2694 {
2695 VariantHierarchy.Parse( cNode, aContext );
2696 }
2697 else if( cNodeName == wxT( "ERRORMARK" ) )
2698 {
2699 //ignore (this is a DRC error marker in cadstar)
2700 continue;
2701 }
2702 else
2703 {
2704 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2705 }
2706
2707 aContext->CheckPointCallback();
2708 }
2709}
constexpr double PCB_IU_PER_MM
Pcbnew IU is 1 nanometer.
Definition base_units.h:68
#define WARN_UNKNOWN_NODE_IO_ERROR(nodename, location)
#define THROW_MISSING_NODE_IO_ERROR(nodename, location)
#define WARN_UNKNOWN_PARAMETER_IO_ERROR(param, location)
#define THROW_MISSING_PARAMETER_IO_ERROR(param, location)
#define THROW_PARSING_IO_ERROR(param, location)
static UNITS ParseUnits(XNODE *aNode)
static SWAP_RULE ParseSwapRule(XNODE *aNode)
static void CheckNoNextNodes(XNODE *aNode)
static XNODE * LoadArchiveFile(const wxString &aFileName, const wxString &aFileTypeIdentifier, PROGRESS_REPORTER *aProgressReporter=nullptr)
Reads a CADSTAR Archive file (S-parameter format).
wxString LAYER_ID
ID of a Sheet (if schematic) or board Layer (if PCB)
static ANGUNITS ParseAngunits(XNODE *aNode)
long PART_DEFINITION_PIN_ID
Pin identifier in the part definition.
static wxString GetXmlAttributeIDString(XNODE *aNode, unsigned int aID, bool aIsRequired=true)
void checkPoint()
Updates m_progressReporter or throws if user canceled.
static bool IsValidAttribute(wxXmlAttribute *aAttribute)
static READABILITY ParseReadability(XNODE *aNode)
static void CheckNoChildNodes(XNODE *aNode)
static long GetXmlAttributeIDLong(XNODE *aNode, unsigned int aID, bool aIsRequired=true)
static void ParseChildEValue(XNODE *aNode, PARSER_CONTEXT *aContext, EVALUE &aValueToParse)
static long GetNumberOfStepsForReporting(XNODE *aRootNode, std::vector< wxString > aSubNodeChildrenToCount)
PROGRESS_REPORTER * m_progressReporter
static TESTLAND_SIDE ParseTestlandSide(XNODE *aNode)
@ STARPOINT
From CADSTAR Help: "Starpoints are special symbols/components that can be used to electrically connec...
@ JUMPER
From CADSTAR Help: "Jumpers are components used primarily for the purpose of routing.
@ COMPONENT
Standard PCB Component definition.
@ TESTPOINT
From CADSTAR Help: "A testpoint is an area of copper connected to a net.
long PAD_ID
Pad identifier (pin) in the PCB.
void Parse(bool aLibrary=false)
Parses the file.
int KiCadUnitMultiplier
Use this value to convert units in this CPA file to KiCad units.
@ ALLELEC
Inbuilt layer type (cannot be assigned to user layers)
@ ALLDOC
Inbuilt layer type (cannot be assigned to user layers)
@ NOLAYER
Inbuilt layer type (cannot be assigned to user layers)
@ JUMPERLAYER
Inbuilt layer type (cannot be assigned to user layers)
@ ALLLAYER
Inbuilt layer type (cannot be assigned to user layers)
@ ASSCOMPCOPP
Inbuilt layer type (cannot be assigned to user layers)
@ MAX
The highest PHYSICAL_LAYER_ID currently defined (i.e. back / bottom side).
@ MIN
The lowest PHYSICAL_LAYER_ID currently defined (i.e. front / top side).
static PAD_SIDE GetPadSide(const wxString &aPadSideString)
PAD_SIDE
From CADSTAR Help: "This parameter indicates the physical layers on which the selected pad is placed.
@ MAXIMUM
The highest PHYSICAL_LAYER_ID currently defined (i.e.
@ THROUGH_HOLE
All physical layers currently defined.
An extension of wxXmlNode that can format its contents as KiCad-style s-expressions.
Definition xnode.h:67
XNODE * GetChildren() const
Definition xnode.h:97
XNODE * GetNext() const
Definition xnode.h:102
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition macros.h:79
static wxString nodeName(const wxString &aSymbolPin)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
NETELEMENT_ID ID
First character is "J".
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
std::function< void()> CheckPointCallback
Callback function to report progress.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
bool Stub
When the CADSTAR Archive file is exported without the component library, if components on the board a...
wxString ReferenceName
This is the name which identifies the symbol in the library Multiple components may exist with the sa...
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
From CADSTAR Help: "Area is for creating areas within which, and nowhere else, certain operations are...
GROUP_ID GroupID
If not empty, this AREA is part of a group.
bool Keepout
From CADSTAR Help: "Auto Placement cannot place components within this area.
bool Placement
From CADSTAR Help: "Auto Placement can place components within this area.
bool NoVias
From CADSTAR Help: "No vias will be placed within this area by the automatic router.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
long AreaHeight
From CADSTAR Help: "The Height value specified for the PCB component is checked against the Height va...
bool Routing
From CADSTAR Help: "Area can be used to place routes during Automatic Routing.
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
bool NoTracks
From CADSTAR Help: "Area cannot be used to place routes during automatic routing.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
GROUP_ID GroupID
Normally CADSTAR_BOARD cannot be part of a reuseblock, but included for completeness.
bool Fixed
If not empty, this CADSTAR_BOARD is part of a group.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< COPPERCODE_ID, COPPERCODE > CopperCodes
std::map< RULESET_ID, RULESET > Rulesets
Used for area design rules.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< SPACINGCODE_ID, SPACINGCODE > SpacingCodes
Spacing Design Rules.
std::map< LAYERPAIR_ID, LAYERPAIR > LayerPairs
Default vias to use between pairs of layers.
From CADSTAR Help: "Area is for creating areas within which, and nowhere else, certain operations are...
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool NoVias
From CADSTAR Help: "Check this button to specify that any area created by the Rectangle,...
bool NoTracks
From CADSTAR Help: "Check this button to specify that any area created by the Rectangle,...
A shape of copper in the component footprint.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool PCBonlyPad
From CADSTAR Help: "The PCB Only Pad property can be used to stop ECO Update, Back Annotation,...
POINT Position
Pad position within the component's coordinate frame.
wxString Identifier
This is an identifier that is displayed to the user.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool FirstPad
From CADSTAR Help: "Only one pad can have this property; if an existing pad in the design already has...
wxString Name
Designator e.g. "C1", "R1", etc.
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
bool TestPoint
Indicates whether this component should be treated as a testpoint.
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
std::map< PAD_ID, PADEXCEPTION > PadExceptions
Override pad definitions for this instance.
std::map< ATTRIBUTE_ID, TEXT_LOCATION > TextLocations
This contains location of any attributes, including designator position.
std::map< PART_DEFINITION_PIN_ID, PIN_ATTRIBUTE > PinAttributes
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
GROUP_ID GroupID
If not empty, this component is part of a group.
std::map< PART_DEFINITION_PIN_ID, wxString > PinLabels
This is inherited from the PARTS library but is allowed to be out of sync.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< COPPER_TERM_ID, COPPER_TERM > CopperTerminals
GROUP_ID GroupID
If not empty, this COPPER is part of a group.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
TEMPLATE_ID PouredTemplateID
If not empty, it means this COPPER is part of a poured template.
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
@ CLOSED
The arrow head is made up of two angled lines either side of main line plus two other lines perpendic...
@ CLEAR
Same as closed but the main line finishes at the start of the perpendicular lines.
@ CLOSED_FILLED
The same as CLOSED or CLEAR arrows, but with a solid fill "DIMENSION_ARROWCLOSEDFILLED".
@ OPEN
The arrow head is made up of two angled lines either side of main line.
long ArrowLength
The length of the angled lines that make up the arrow head.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool SuppressFirst
If true, excludes the first extension line (only shows extension line at end)
long Overshoot
Overshoot of the extension line past the arrow line.
@ INTERNAL
The lines are placed inside the measurement token=DIMENSION_INTERNAL.
@ EXTERNAL
The lines are placed outside the measurement (typically used when limited space) token=DIMENSION_EXTE...
long LeaderLineExtensionLength
Only for TYPE=LEADERLINE Length of the horizontal part of the leader line [param6].
long LeaderLineLength
Only for TYPE=LEADERLINE Length of the angled part of the leader line [param5].
long LeaderAngle
Only for TYPE=LEADERLINE subnode "LEADERANG".
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
POINT Centre
Only for TYPE=ANGULARLINE [point3].
long TextGap
Specifies the gap between the text and the end of the line.
long TextOffset
Specifies how far above the line the text is (doesn't have an effect on actual position!...
@ INSIDE
Embedded with the line (the Gap parameter specifies the gap between the text and the end of the line)...
@ OUTSIDE
Above the line (the Offset parameter specifies how far above the line the text is) DIMENSION_EXTERNAL...
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
Linear, leader (radius/diameter) or angular dimension.
LAYER_ID LayerID
ID on which to draw this [param1].
@ DIRECT
A linear dimension parallel to measurement with perpendicular extension lines token=DIMENSION_DIRECT.
@ ORTHOGONAL
An orthogonal dimension (either x or y measurement) token=DIMENSION_ORTHOGONAL.
@ ANGLED
A linear dimension parallel to measurement but with orthogonal extension lines (i....
GROUP_ID GroupID
If not empty, this DIMENSION is part of a group.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
EXTENSION_LINE ExtensionLineParams
Not applicable to TYPE=LEADERDIM.
DIMENSION_ID ID
Some ID (doesn't seem to be used) subnode="DIMREF".
long Precision
Number of decimal points to display in the measurement [param3].
ANGUNITS AngularUnits
Only Applicable to TYPE=ANGLEDIM.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
GROUP_ID GroupID
If not empty, this DRILL_TABLE is part of a group.
std::map< MATERIAL_ID, MATERIAL > Materials
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
PHYSICAL_LAYER_ID PhysicalLayer
If UNDEFINED, no physical layer is assigned (e.g.
long Thickness
Note: Units of length are defined in file header.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< TEMPLATE_ID, TEMPLATE > Templates
std::map< BOARD_ID, CADSTAR_BOARD > Boards
Normally CADSTAR only allows one board but.
std::map< NET_ID, NET_PCB > Nets
Contains tracks and vias.
std::map< COMPONENT_ID, COMPONENT > Components
std::map< DOCUMENTATION_SYMBOL_ID, DOCUMENTATION_SYMBOL > DocumentationSymbols
std::map< DIMENSION_ID, DIMENSION > Dimensions
std::map< REUSEBLOCK_ID, REUSEBLOCK > ReuseBlocks
std::map< DRILL_TABLE_ID, DRILL_TABLE > DrillTables
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< SYMDEF_ID, SYMDEF_PCB > ComponentDefinitions
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool Unrouted
Instead of a ROUTE, the CONNECTION might have an "UNROUTE" token.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
< "PIN" nodename (represents a PAD in a PCB component)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
< Two sibbling nodes: first node being "ROUTEWIDTH" and next node being a VERTEX (e....
XNODE * Parse(XNODE *aNode, PARSER_CONTEXT *aContext)
bool RouteWidthIsExplicit
False if ROUTEWIDTH was not specified in file.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
GROUP_ID GroupID
If not empty, this VIA is part of a group.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< NETELEMENT_ID, COPPER_TERMINAL > CopperTerminals
std::map< NETELEMENT_ID, JUNCTION_PCB > Junctions
long ReliefWidth
if undefined inherits from design
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< LAYER_ID, CADSTAR_PAD_SHAPE > Reassigns
long ReliefClearance
if undefined inherits from design
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
PADCODE_ID PadCode
If not empty, override padcode.
bool HasShape
False when the shape node was unknown and skipped.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
ROUTECODE_ID AreaRouteCodeID
For assigning a net route code to a rule set.
VIACODE_ID AreaViaCodeID
For assigning a via code to a rule set.
std::map< SPACINGCODE_ID, SPACINGCODE > SpacingCodes
Overrides these spacing rules in the specific area.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::vector< REASSIGN > Reassigns
Can have different spacings on different layers.
SPACINGCODE_ID ID
Possible spacing rules:
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
LAYER_ID LayerID
Normally LAY0, which corresponds to (All Layers)
std::map< PAD_ID, COMPONENT_PAD > ComponentPads
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< DIMENSION_ID, DIMENSION > Dimensions
inside "DIMENSIONS" subnode
std::vector< COMPONENT_COPPER > ComponentCoppers
long SymHeight
The Height of the component (3D height in z direction)
std::map< COMP_AREA_ID, COMPONENT_AREA > ComponentAreas
long MinRouteWidth
Manufacturing Design Rule. Corresponds to "Thin Route Width".
long TrackGrid
Grid for Routes (equal X and Y steps)
long MaxPhysicalLayer
Should equal number of copper layers.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
long MaxMitre
Manufacturing Design Rule. Corresponds to "Maximum Mitre".
long ViaGrid
Grid for Vias (equal X and Y steps)
long MinMitre
Manufacturing Design Rule. Corresponds to "Minimum Mitre".
long AdditionalIsolation
This is the gap to apply in routes and pads in addition to the existing pad-to-copper or route-to-cop...
bool TargetForAutorouting
true when subnode "AUTOROUTETARGET" is present
bool ThermalReliefOnVias
false when subnode "NOVIARELIEF" is present
@ CUTOUTS
This method uses four cutouts in the copper to leave the reliefs required.
HATCHCODE_ID HatchCodeID
Only for FillType = HATCHED.
bool ThermalReliefOnPads
false when subnode "NOPINRELIEF" is present
long ThermalReliefPadsAngle
Orientation for the thermal reliefs.
long MinDisjointCopper
The value is the length of one side of a notional square.
bool AutomaticRepour
true when subnode "REGENERATE" is present
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool AllowInNoRouting
true when subnode "IGNORETRN" is present
bool BoxIsolatedPins
true when subnode "BOXPINS" is present
long ClearanceWidth
Specifies the space around pads when pouring (i.e.
COPPERCODE_ID ReliefCopperCodeID
From CADSTAR Help: "Relief Copper Code is forselecting the width of line used to draw thethermal reli...
COPPERCODE_ID CopperCodeID
From CADSTAR Help: "Copper Code is for selecting the width of the line used to draw the outline and f...
long ThermalReliefViasAngle
Disabled when !ThermalReliefOnVias (param6)
long MinIsolatedCopper
The value is the length of one side of a notional square.
long SliverWidth
Minimum width of copper that may be created.
Templates are CADSTAR's equivalent to a "filled zone".
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
POURING Pouring
Copper pour settings (e.g. relief / hatching /etc.)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
GROUP_ID GroupID
If not empty, this TEMPLATE is part of a group.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
long ReliefClearance
if undefined inherits from design
long ReliefWidth
if undefined inherits from design
std::map< LAYER_ID, CADSTAR_PAD_SHAPE > Reassigns
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool HasShape
False when the shape node was unknown and skipped.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
KIBIS_COMPONENT * comp
KIBIS_PIN * pin
VECTOR2I location