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 {
85 wxT( "The selected file is a CADSTAR library file (as opposed "
86 "to a layout file). You can import this library by adding it "
87 "to the library table." ) );
88 }
89 else
90 {
91 THROW_IO_ERROR( wxT( "The selected file is an unknown CADSTAR format so "
92 "cannot be imported into KiCad." ) );
93 }
94 }
95 }
96 else if( cNode->GetName() == wxT( "ASSIGNMENTS" ) )
97 {
98 Assignments.Parse( cNode, &m_context );
99 }
100 else if( cNode->GetName() == wxT( "LIBRARY" ) )
101 {
102 Library.Parse( cNode, &m_context );
103 }
104 else if( cNode->GetName() == wxT( "DEFAULTS" ) )
105 {
106 // No design information here (no need to parse)
107 // Only contains CADSTAR configuration data such as default shapes, text and units
108 // In future some of this could be converted to KiCad but limited value
109 }
110 else if( cNode->GetName() == wxT( "PARTS" ) )
111 {
112 Parts.Parse( cNode, &m_context );
113 }
114 else if( cNode->GetName() == wxT( "LAYOUT" ) )
115 {
116 Layout.Parse( cNode, &m_context );
117 }
118 else if( cNode->GetName() == wxT( "DISPLAY" ) )
119 {
120 // No design information here (no need to parse)
121 // Contains CADSTAR Display settings such as layer/element colours and visibility.
122 // In the future these settings could be converted to KiCad
123 }
124 else
125 {
126 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "[root]" ) );
127 }
128
129 checkPoint();
130 }
131
132 delete m_rootNode;
133 m_rootNode = nullptr;
134}
135
136
138{
139 wxASSERT( aNode->GetName() == wxT( "ASSIGNMENTS" ) );
140
141 XNODE* cNode = aNode->GetChildren();
142
143 if( !cNode )
144 THROW_MISSING_NODE_IO_ERROR( wxT( "TECHNOLOGY" ), wxT( "ASSIGNMENTS" ) );
145
146 for( ; cNode; cNode = cNode->GetNext() )
147 {
148 if( cNode->GetName() == wxT( "LAYERDEFS" ) )
149 Layerdefs.Parse( cNode, aContext );
150 else if( cNode->GetName() == wxT( "CODEDEFS" ) )
151 Codedefs.Parse( cNode, aContext );
152 else if( cNode->GetName() == wxT( "TECHNOLOGY" ) )
153 Technology.Parse( cNode, aContext );
154 else if( cNode->GetName() == wxT( "GRIDS" ) )
155 Grids.Parse( cNode, aContext );
156 else if( cNode->GetName() == wxT( "NETCLASSEDITATTRIBSETTINGS" ) )
158 else if( cNode->GetName() == wxT( "SPCCLASSEDITATTRIBSETTINGS" ) )
160 else
161 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
162 }
163}
164
165
167{
168 wxASSERT( aNode->GetName() == wxT( "LAYERDEFS" ) );
169
170 wxXmlAttribute* xmlAttribute = nullptr;
171
172 XNODE* cNode = aNode->GetChildren();
173
174 if( !cNode )
175 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "LAYERSTACK" ), wxT( "LAYERDEFS" ) );
176
177 for( ; cNode; cNode = cNode->GetNext() )
178 {
179 wxString nodeName = cNode->GetName();
180
181 if( nodeName == wxT( "LAYERSTACK" ) )
182 {
183 xmlAttribute = cNode->GetAttributes();
184
185 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
186 {
187 if( !IsValidAttribute( xmlAttribute ) )
188 continue;
189 else
190 LayerStack.push_back( (LAYER_ID) xmlAttribute->GetValue() );
191 }
192
193 CheckNoChildNodes( cNode );
194 }
195 else if( nodeName == wxT( "MATERIAL" ) )
196 {
197 MATERIAL material;
198 material.Parse( cNode, aContext );
199 Materials.insert( std::make_pair( material.ID, material ) );
200 }
201 else if( nodeName == wxT( "LAYER" ) )
202 {
203 LAYER layer;
204 layer.Parse( cNode, aContext );
205 Layers.insert( std::make_pair( layer.ID, layer ) );
206 }
207 else if( nodeName == wxT( "SWAPPAIR" ) )
208 {
209 LAYER_ID layerId = (LAYER_ID) GetXmlAttributeIDString( cNode, 0 );
210 LAYER_ID swapLayerId = (LAYER_ID) GetXmlAttributeIDString( cNode, 1 );
211
212 Layers[layerId].SwapLayerID = swapLayerId;
213 }
214 else
215 {
216 WARN_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
217 }
218 }
219}
220
221
223{
224 wxASSERT( aNode->GetName() == wxT( "RULESET" ) );
225
226 ID = GetXmlAttributeIDString( aNode, 0 );
227 Name = GetXmlAttributeIDString( aNode, 1 );
228
229 XNODE* cNode = aNode->GetChildren();
230
231 for( ; cNode; cNode = cNode->GetNext() )
232 {
233 wxString nodeName = cNode->GetName();
234
235 if( nodeName == wxT( "ROUCODEREF" ) )
236 {
238 }
239 else if( nodeName == wxT( "VIACODEREF" ) )
240 {
242 }
243 else if( nodeName == wxT( "SPACINGCODE" ) )
244 {
245 SPACINGCODE spacingcode;
246 spacingcode.Parse( cNode, aContext );
247 SpacingCodes.insert( std::make_pair( spacingcode.ID, spacingcode ) );
248 }
249 else
250 {
251 WARN_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
252 }
253 }
254}
255
256
258{
259 wxASSERT( aNode->GetName() == wxT( "CODEDEFS" ) );
260
261 XNODE* cNode = aNode->GetChildren();
262
263 for( ; cNode; cNode = cNode->GetNext() )
264 {
265 wxString nodeName = cNode->GetName();
266
267 if( ParseSubNode( cNode, aContext ) ) // in CADSTAR_ARCHIVE_PARSER::CODEDEFS
268 {
269 }
270 else if( nodeName == wxT( "COPPERCODE" ) )
271 {
272 COPPERCODE coppercode;
273 coppercode.Parse( cNode, aContext );
274 CopperCodes.insert( std::make_pair( coppercode.ID, coppercode ) );
275 }
276 else if( nodeName == wxT( "SPACINGCODE" ) )
277 {
278 SPACINGCODE spacingcode;
279 spacingcode.Parse( cNode, aContext );
280 SpacingCodes.insert( std::make_pair( spacingcode.ID, spacingcode ) );
281 }
282 else if( nodeName == wxT( "RULESET" ) )
283 {
284 RULESET ruleset;
285 ruleset.Parse( cNode, aContext );
286 Rulesets.insert( std::make_pair( ruleset.ID, ruleset ) );
287 }
288 else if( nodeName == wxT( "PADCODE" ) )
289 {
290 PADCODE padcode;
291 padcode.Parse( cNode, aContext );
292 PadCodes.insert( std::make_pair( padcode.ID, padcode ) );
293 }
294 else if( nodeName == wxT( "VIACODE" ) )
295 {
296 VIACODE viacode;
297 viacode.Parse( cNode, aContext );
298 ViaCodes.insert( std::make_pair( viacode.ID, viacode ) );
299 }
300 else if( nodeName == wxT( "LAYERPAIR" ) )
301 {
302 LAYERPAIR layerpair;
303 layerpair.Parse( cNode, aContext );
304 LayerPairs.insert( std::make_pair( layerpair.ID, layerpair ) );
305 }
306 else if( nodeName == wxT( "SPCCLASSSPACE" ) )
307 {
308 SPCCLASSSPACE spcclassspace;
309 spcclassspace.Parse( cNode, aContext );
310 SpacingClasses.push_back( spcclassspace );
311 }
312 else
313 {
314 WARN_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() );
315 }
316 }
317}
318
319
321{
322 wxASSERT( aNode->GetName() == wxT( "MATERIAL" ) );
323
324 ID = GetXmlAttributeIDString( aNode, 0 );
325 Name = GetXmlAttributeIDString( aNode, 1 );
326
327 wxString sType = GetXmlAttributeIDString( aNode, 2 );
328
329 if( sType == wxT( "CONSTRUCTION" ) )
330 {
332 }
333 else if( sType == wxT( "ELECTRICAL" ) )
334 {
336 }
337 else if( sType == wxT( "NONELEC" ) )
338 {
340 }
341 else
342 {
343 WARN_UNKNOWN_PARAMETER_IO_ERROR( sType, wxString::Format( wxT( "MATERIAL %s" ), Name ) );
344 }
345
346 XNODE* iNode = aNode->GetChildren();
347
348 if( !iNode )
349 {
350 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "RESISTIVITY" ),
351 wxString::Format( wxT( "MATERIAL %s" ), Name ) );
352 }
353
354 for( ; iNode; iNode = iNode->GetNext() )
355 {
356 wxString nodeName = iNode->GetName();
357
358 if( nodeName == wxT( "RELPERMIT" ) )
359 {
360 ParseChildEValue( iNode, aContext, Permittivity );
361 }
362 else if( nodeName == wxT( "LOSSTANGENT" ) )
363 {
364 ParseChildEValue( iNode, aContext, LossTangent );
365 }
366 else if( nodeName == wxT( "RESISTIVITY" ) )
367 {
368 ParseChildEValue( iNode, aContext, Resistivity );
369 }
370 else
371 {
372 WARN_UNKNOWN_NODE_IO_ERROR( nodeName, wxString::Format( wxT( "MATERIAL %s" ), Name ) );
373 }
374 }
375}
376
377
379{
380 wxASSERT( aNode->GetName() == wxT( "LAYER" ) );
381
382 ID = GetXmlAttributeIDString( aNode, 0 );
383 Name = GetXmlAttributeIDString( aNode, 1 );
384
385 XNODE* cNode = aNode->GetChildren();
386 auto processLayerMaterialDetails = [&]() {
387 XNODE* tempNode = cNode->GetChildren();
388 for( ; tempNode; tempNode = tempNode->GetNext() )
389 {
390 wxString tempNodeName = tempNode->GetName();
391
392 if( tempNodeName == wxT( "MAKE" ) || tempNodeName == wxT( "LAYERHEIGHT" ) )
393 {
394 if( tempNodeName == wxT( "LAYERHEIGHT" ) )
395 {
396 Thickness = GetXmlAttributeIDLong( tempNode, 0 );
397 }
398 else
399 {
400 MaterialId = GetXmlAttributeIDString( tempNode, 0 );
401 Thickness = GetXmlAttributeIDLong( tempNode, 1 );
402 }
403
404 XNODE* childOfTempNode = tempNode->GetChildren();
405
406 if( childOfTempNode )
407 {
408 if( childOfTempNode->GetName() == wxT( "EMBEDS" ) )
409 {
410 wxString embedsValue = GetXmlAttributeIDString( childOfTempNode, 0 );
411
412 if( embedsValue == wxT( "UPWARDS" ) )
413 {
415 }
416 else if( embedsValue == wxT( "DOWNWARDS" ) )
417 {
419 }
420 else
421 {
423 wxString::Format( wxT( "LAYER %s -> EMBEDS" ),
424 Name ) );
425 }
426 }
427 else
428 {
429 WARN_UNKNOWN_NODE_IO_ERROR( childOfTempNode->GetName(),
430 wxString::Format( wxT( "LAYER %s->MAKE" ),
431 Name ) );
432 }
433 }
434 }
435 else if( tempNodeName == wxT( "BIAS" ) )
436 {
437 wxString bias = GetXmlAttributeIDString( tempNode, 0 );
438
439 if( bias == wxT( "X_BIASED" ) )
440 {
442 }
443 else if( bias == wxT( "Y_BIASED" ) )
444 {
446 }
447 else if( bias == wxT( "ANTITRACK" ) )
448 {
450 }
451 else if( bias == wxT( "OBSTACLE" ) )
452 {
454 }
455 else if( bias == wxT( "UNBIASED" ) )
456 {
458 }
459 else
460 {
462 wxString::Format( wxT( "LAYER %s -> BIAS" ),
463 Name ) );
464 }
465 }
466 else
467 {
468 WARN_UNKNOWN_NODE_IO_ERROR( tempNodeName, wxString::Format( wxT( "LAYER %s" ),
469 Name ) );
470 }
471 }
472 };
473
474 for( ; cNode; cNode = cNode->GetNext() )
475 {
476 wxString cNodeName = cNode->GetName();
477
478 if( cNodeName == wxT( "ALLDOC" ) )
479 {
481 }
482 else if( cNodeName == wxT( "ALLELEC" ) )
483 {
485 }
486 else if( cNodeName == wxT( "ALLLAYER" ) )
487 {
489 }
490 else if( cNodeName == wxT( "ASSCOMPCOPP" ) )
491 {
493 }
494 else if( cNodeName == wxT( "JUMPERLAYER" ) )
495 {
497 }
498 else if( cNodeName == wxT( "NOLAYER" ) )
499 {
501 }
502 else if( cNodeName == wxT( "POWER" ) )
503 {
506 processLayerMaterialDetails();
507 }
508 else if( cNodeName == wxT( "DOC" ) )
509 {
511 }
512 else if( cNodeName == wxT( "CONSTRUCTION" ) )
513 {
515 processLayerMaterialDetails();
516 }
517 else if( cNodeName == wxT( "ELEC" ) )
518 {
521 processLayerMaterialDetails();
522 }
523 else if( cNodeName == wxT( "NONELEC" ) )
524 {
527 processLayerMaterialDetails();
528 }
529 else if( cNodeName == wxT( "DESCRIPTION" ) )
530 {
532 }
533 else if( cNodeName == wxT( "REFPLANE" ) )
534 {
535 ReferencePlane = true;
536 }
537 else if( cNodeName == wxT( "VLAYER" ) )
538 {
539 VariantLayer = true;
540 }
541 else if( cNodeName == wxT( "LASUBTYP" ) )
542 {
543 //Process subtype
544 wxString sSubType = GetXmlAttributeIDString( cNode, 0 );
545
546 if( sSubType == wxT( "LAYERSUBTYPE_ASSEMBLY" ) )
547 {
549 }
550 else if( sSubType == wxT( "LAYERSUBTYPE_PASTE" ) )
551 {
553 }
554 else if( sSubType == wxT( "LAYERSUBTYPE_PLACEMENT" ) )
555 {
557 }
558 else if( sSubType == wxT( "LAYERSUBTYPE_SILKSCREEN" ) )
559 {
561 }
562 else if( sSubType == wxT( "LAYERSUBTYPE_SOLDERRESIST" ) )
563 {
565 }
566 else if( sSubType == wxT( "LAYERSUBTYPE_CLEARANCE" ) )
567 {
569 }
570 else if( sSubType == wxT( "LAYERSUBTYPE_ROUT" ) )
571 {
573 }
574 else
575 {
576 WARN_UNKNOWN_PARAMETER_IO_ERROR( sSubType, wxString::Format( wxT( "LAYER %s %s" ),
577 Name, cNodeName ) );
578 }
579 }
580 else
581 {
582 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxString::Format( wxT( "LAYER %s" ), Name ) );
583 }
584 }
585}
586
587
589{
590 wxASSERT( aNode->GetName() == wxT( "COPREASSIGN" ) );
591
592 LayerID = GetXmlAttributeIDString( aNode, 0 );
593
595}
596
597
599{
600 wxASSERT( aNode->GetName() == wxT( "COPPERCODE" ) );
601
602 ID = GetXmlAttributeIDString( aNode, 0 );
603 Name = GetXmlAttributeIDString( aNode, 1 );
604
606
607 XNODE* cNode = aNode->GetChildren();
608
609 for( ; cNode; cNode = cNode->GetNext() )
610 {
611 if( cNode->GetName() == wxT( "COPREASSIGN" ) )
612 {
614 reassign.Parse( cNode, aContext );
615 Reassigns.push_back( reassign );
616 }
617 else
618 {
619 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
620 }
621 }
622}
623
624
626 PARSER_CONTEXT* aContext )
627{
628 wxASSERT( aNode->GetName() == wxT( "SPACEREASSIGN" ) );
629
630 LayerID = GetXmlAttributeIDString( aNode, 0 );
631 Spacing = GetXmlAttributeIDLong( aNode, 1 );
632
633 CheckNoChildNodes( aNode );
634}
635
636
638{
639 wxASSERT( aNode->GetName() == wxT( "SPACINGCODE" ) );
640
641 ID = GetXmlAttributeIDString( aNode, 0 );
642 Spacing = GetXmlAttributeIDLong( aNode, 1 );
643
644 XNODE* cNode = aNode->GetChildren();
645
646 for( ; cNode; cNode = cNode->GetNext() )
647 {
648 wxString cNodeName = cNode->GetName();
649
650 if( cNodeName == wxT( "SPACEREASSIGN" ) )
651 {
652 REASSIGN reassign;
653 reassign.Parse( cNode, aContext );
654 Reassigns.push_back( reassign );
655 }
656 else
657 {
658 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
659 }
660 }
661}
662
663
665{
666 if( !aNode )
667 return false;
668
669 wxString aNodeName = aNode->GetName();
670
671 if( aNodeName == wxT( "ANNULUS" ) || aNodeName == wxT( "BULLET" ) || aNodeName == wxT( "ROUND" )
672 || aNodeName == wxT( "DIAMOND" ) || aNodeName == wxT( "FINGER" )
673 || aNodeName == wxT( "OCTAGON" ) || aNodeName == wxT( "RECTANGLE" )
674 || aNodeName == wxT( "ROUNDED" ) || aNodeName == wxT( "SQUARE" ) )
675 {
676 return true;
677 }
678 else
679 {
680 return false;
681 }
682}
683
684
686{
687 wxASSERT( IsPadShape( aNode ) );
688
689 wxString aNodeName = aNode->GetName();
690
691 if( aNodeName == wxT( "ANNULUS" ) )
693 else if( aNodeName == wxT( "BULLET" ) )
695 else if( aNodeName == wxT( "ROUND" ) )
697 else if( aNodeName == wxT( "DIAMOND" ) )
699 else if( aNodeName == wxT( "FINGER" ) )
701 else if( aNodeName == wxT( "OCTAGON" ) )
703 else if( aNodeName == wxT( "RECTANGLE" ) )
705 else if( aNodeName == wxT( "ROUNDED" ) )
707 else if( aNodeName == wxT( "SQUARE" ) )
709 else
710 wxASSERT( true );
711
712 switch( ShapeType )
713 {
715 Size = GetXmlAttributeIDLong( aNode, 0 );
717 break;
718
722
727 LeftLength = GetXmlAttributeIDLong( aNode, 1 );
729
733 if( aNode->GetChildren() )
734 {
735 if( aNode->GetChildren()->GetName() == wxT( "ORIENT" ) )
736 {
738 }
739 else
740 {
741 WARN_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
742 }
743
744 CheckNoNextNodes( aNode->GetChildren() );
745 }
747
749 Size = GetXmlAttributeIDLong( aNode, 0 );
750 break;
751 }
752}
753
754
756{
757 wxASSERT( aNode->GetName() == wxT( "PADREASSIGN" ) );
758
759 LayerID = GetXmlAttributeIDString( aNode, 0 );
760
761 XNODE* shapeNode = aNode->GetChildren();
762
763 if( CADSTAR_PAD_SHAPE::IsPadShape( shapeNode ) )
764 {
765 Shape.Parse( shapeNode, aContext );
766 HasShape = true;
767 }
768 else
769 {
770 wxString found = shapeNode ? shapeNode->GetName() : wxString( "(empty)" );
771 WARN_UNKNOWN_NODE_IO_ERROR( found, aNode->GetName() );
772 }
773
774 CheckNoNextNodes( shapeNode );
775}
776
777
779{
780 wxASSERT( aNode->GetName() == wxT( "PADCODE" ) );
781
782 ID = GetXmlAttributeIDString( aNode, 0 );
783 Name = GetXmlAttributeIDString( aNode, 1 );
784
785 XNODE* cNode = aNode->GetChildren();
786 wxString location = wxString::Format( wxT( "PADCODE -> %s" ), Name );
787
788 for( ; cNode; cNode = cNode->GetNext() )
789 {
790 wxString cNodeName = cNode->GetName();
791
792 if( CADSTAR_PAD_SHAPE::IsPadShape( cNode ) )
793 {
794 Shape.Parse( cNode, aContext );
795 }
796 else if( cNodeName == wxT( "CLEARANCE" ) )
797 {
799 }
800 else if( cNodeName == wxT( "RELIEFWIDTH" ) )
801 {
803 }
804 else if( cNodeName == wxT( "DRILL" ) )
805 {
807 XNODE* subNode = cNode->GetChildren();
808
809 for( ; subNode; subNode = subNode->GetNext() )
810 {
811 wxString subNodeName = subNode->GetName();
812
813 if( subNodeName == wxT( "NONPLATED" ) )
814 Plated = false;
815 else if( subNodeName == wxT( "OVERSIZE" ) )
816 DrillOversize = GetXmlAttributeIDLong( subNode, 0 );
817 else
818 WARN_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
819 }
820 }
821 else if( cNodeName == wxT( "DRILLLENGTH" ) )
822 {
823 SlotLength = GetXmlAttributeIDLong( cNode, 0 );
824 }
825 else if( cNodeName == wxT( "DRILLORIENTATION" ) )
826 {
828 }
829 else if( cNodeName == wxT( "DRILLXOFFSET" ) )
830 {
832 }
833 else if( cNodeName == wxT( "DRILLYOFFSET" ) )
834 {
836 }
837 else if( cNodeName == wxT( "PADREASSIGN" ) )
838 {
839 PADREASSIGN reassign;
840 reassign.Parse( cNode, aContext );
841
842 if( reassign.HasShape )
843 Reassigns.insert( std::make_pair( reassign.LayerID, reassign.Shape ) );
844 }
845 else
846 {
848 }
849 }
850}
851
852
854{
855 wxASSERT( aNode->GetName() == wxT( "VIAREASSIGN" ) );
856
857 LayerID = GetXmlAttributeIDString( aNode, 0 );
858
859 XNODE* shapeNode = aNode->GetChildren();
860
861 if( CADSTAR_PAD_SHAPE::IsPadShape( shapeNode ) )
862 {
863 Shape.Parse( shapeNode, aContext );
864 HasShape = true;
865 }
866 else
867 {
868 wxString found = shapeNode ? shapeNode->GetName() : wxString( "(empty)" );
869 WARN_UNKNOWN_NODE_IO_ERROR( found, aNode->GetName() );
870 }
871
872 CheckNoNextNodes( shapeNode );
873}
874
875
877{
878 wxASSERT( aNode->GetName() == wxT( "VIACODE" ) );
879
880 ID = GetXmlAttributeIDString( aNode, 0 );
881 Name = GetXmlAttributeIDString( aNode, 1 );
882
883 XNODE* cNode = aNode->GetChildren();
884 wxString location = wxString::Format( wxT( "VIACODE -> %s" ), Name );
885
886 for( ; cNode; cNode = cNode->GetNext() )
887 {
888 wxString cNodeName = cNode->GetName();
889
890 if( CADSTAR_PAD_SHAPE::IsPadShape( cNode ) )
891 {
892 Shape.Parse( cNode, aContext );
893 }
894 else if( cNodeName == wxT( "CLEARANCE" ) )
895 {
897 }
898 else if( cNodeName == wxT( "RELIEFWIDTH" ) )
899 {
901 }
902 else if( cNodeName == wxT( "DRILL" ) )
903 {
905 XNODE* subNode = cNode->GetChildren();
906
907 for( ; subNode; subNode = subNode->GetNext() )
908 {
909 wxString subNodeName = subNode->GetName();
910
911 if( subNodeName == wxT( "OVERSIZE" ) )
912 DrillOversize = GetXmlAttributeIDLong( subNode, 0 );
913 else
914 WARN_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), location );
915 }
916 }
917 else if( cNodeName == wxT( "VIAREASSIGN" ) )
918 {
919 VIAREASSIGN reassign;
920 reassign.Parse( cNode, aContext );
921
922 if( reassign.HasShape )
923 Reassigns.insert( std::make_pair( reassign.LayerID, reassign.Shape ) );
924 }
925 else
926 {
928 }
929 }
930}
931
932
934{
935 wxASSERT( aNode->GetName() == wxT( "LAYERPAIR" ) );
936
937 ID = GetXmlAttributeIDString( aNode, 0 );
938 Name = GetXmlAttributeIDString( aNode, 1 );
939
942
943 wxString location = wxString::Format( wxT( "LAYERPAIR -> %s" ), Name );
944
945 if( aNode->GetChildren() )
946 {
947 if( aNode->GetChildren()->GetName() == wxT( "VIACODEREF" ) )
948 {
950 }
951 else
952 {
953 WARN_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), location );
954 }
955
956 CheckNoNextNodes( aNode->GetChildren() );
957 }
958}
959
960
962{
963 wxASSERT( aNode->GetName() == wxT( "SPCCLASSSPACE" ) );
964
967 LayerID = GetXmlAttributeIDString( aNode, 2 );
968 Spacing = GetXmlAttributeIDLong( aNode, 3 );
969}
970
971
973{
974 wxASSERT( aNode->GetName() == wxT( "TECHNOLOGY" ) );
975
976 XNODE* cNode = aNode->GetChildren();
977
978 for( ; cNode; cNode = cNode->GetNext() )
979 {
980 wxString cNodeName = cNode->GetName();
981
982 if( ParseSubNode( cNode, aContext ) ) //CADSTAR_ARCHIVE_PARSER::SETTINGS
983 {
984 }
985 else if( cNodeName == wxT( "MINROUTEWIDTH" ) )
986 {
988 }
989 else if( cNodeName == wxT( "MINNECKED" ) )
990 {
992 }
993 else if( cNodeName == wxT( "MINUNNECKED" ) )
994 {
996 }
997 else if( cNodeName == wxT( "MINMITER" ) )
998 {
999 MinMitre = GetXmlAttributeIDLong( cNode, 0 );
1000 }
1001 else if( cNodeName == wxT( "MAXMITER" ) )
1002 {
1003 MaxMitre = GetXmlAttributeIDLong( cNode, 0 );
1004 }
1005 else if( cNodeName == wxT( "MAXPHYSLAYER" ) )
1006 {
1008 }
1009 else if( cNodeName == wxT( "TRACKGRID" ) )
1010 {
1011 TrackGrid = GetXmlAttributeIDLong( cNode, 0 );
1012 }
1013 else if( cNodeName == wxT( "VIAGRID" ) )
1014 {
1015 ViaGrid = GetXmlAttributeIDLong( cNode, 0 );
1016 }
1017 else if( cNodeName == wxT( "BACKOFFJCTS" ) )
1018 {
1019 BackOffJunctions = true;
1020 }
1021 else if( cNodeName == wxT( "BCKOFFWIDCHANGE" ) )
1022 {
1023 BackOffWidthChange = true;
1024 }
1025 else
1026 {
1027 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TECHNOLOGY" ) );
1028 }
1029 }
1030}
1031
1032
1034 const wxString& aPadSideString )
1035{
1036 if( aPadSideString == wxT( "THRU" ) )
1038 else if( aPadSideString == wxT( "BOTTOM" ) )
1039 return PAD_SIDE::MAXIMUM;
1040 else if( aPadSideString == wxT( "TOP" ) )
1041 return PAD_SIDE::MINIMUM;
1042 else
1043 return PAD_SIDE::THROUGH_HOLE; // Assume through hole as default
1044}
1045
1046
1048{
1049 wxASSERT( aNode->GetName() == wxT( "COMPCOPPER" ) );
1050
1052 LayerID = GetXmlAttributeIDString( aNode, 1 );
1053
1054 XNODE* cNode = aNode->GetChildren();
1055 bool shapeIsInitialised = false; // Stop more than one Shape Object
1056 wxString location = wxT( "COMPCOPPER" );
1057
1058 if( !cNode )
1059 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1060
1061 for( ; cNode; cNode = cNode->GetNext() )
1062 {
1063 wxString cNodeName = cNode->GetName();
1064
1065 if( !shapeIsInitialised && Shape.IsShape( cNode ) )
1066 {
1067 Shape.Parse( cNode, aContext );
1068 shapeIsInitialised = true;
1069 }
1070 else if( cNodeName == wxT( "SWAPRULE" ) )
1071 {
1072 SwapRule = ParseSwapRule( cNode );
1073 }
1074 else if( cNodeName == wxT( "ASSOCPIN" ) )
1075 {
1076 wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
1077
1078 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1079 {
1080 if( !IsValidAttribute( xmlAttribute ) )
1081 continue;
1082
1083 long padId;
1084
1085 if( !xmlAttribute->GetValue().ToLong( &padId ) )
1086 THROW_PARSING_IO_ERROR( wxT( "ASSOCPIN" ), location );
1087
1088 AssociatedPadIDs.push_back( (PAD_ID) padId );
1089 }
1090
1091 CheckNoChildNodes( cNode );
1092 }
1093 else
1094 {
1096 }
1097 }
1098}
1099
1100
1102{
1103 wxASSERT( aNode->GetName() == wxT( "COMPAREA" ) );
1104
1105 ID = GetXmlAttributeIDString( aNode, 0 );
1106 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1107 LayerID = GetXmlAttributeIDString( aNode, 3 );
1108
1109 XNODE* cNode = aNode->GetChildren();
1110 bool shapeIsInitialised = false; // Stop more than one Shape Object
1111 wxString location = wxString::Format( wxT( "COMPAREA %s" ), ID );
1112
1113 if( !cNode )
1114 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1115
1116 for( ; cNode; cNode = cNode->GetNext() )
1117 {
1118 wxString cNodeName = cNode->GetName();
1119
1120 if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
1121 {
1122 Shape.Parse( cNode, aContext );
1123 shapeIsInitialised = true;
1124 }
1125 else if( cNodeName == wxT( "SWAPRULE" ) )
1126 {
1127 SwapRule = ParseSwapRule( cNode );
1128 }
1129 else if( cNodeName == wxT( "USAGE" ) )
1130 {
1131 wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
1132
1133 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1134 {
1135 if( !IsValidAttribute( xmlAttribute ) )
1136 continue;
1137
1138 if( xmlAttribute->GetValue() == wxT( "NO_TRACKS" ) )
1139 NoTracks = true;
1140 else if( xmlAttribute->GetValue() == wxT( "NO_VIAS" ) )
1141 NoVias = true;
1142 else
1143 WARN_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), location );
1144 }
1145
1146 CheckNoChildNodes( cNode );
1147 }
1148 else
1149 {
1151 }
1152 }
1153}
1154
1155
1157{
1158 wxASSERT( aNode->GetName() == wxT( "EXITS" ) );
1159
1160 wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
1161
1162 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1163 {
1164 if( !IsValidAttribute( xmlAttribute ) )
1165 continue;
1166
1167 if( xmlAttribute->GetValue() == wxT( "FREE" ) )
1168 FreeAngle = true;
1169 else if( xmlAttribute->GetValue() == wxT( "N" ) )
1170 North = true;
1171 else if( xmlAttribute->GetValue() == wxT( "S" ) )
1172 South = true;
1173 else if( xmlAttribute->GetValue() == wxT( "E" ) )
1174 East = true;
1175 else if( xmlAttribute->GetValue() == wxT( "W" ) )
1176 West = true;
1177 else if( xmlAttribute->GetValue() == wxT( "NE" ) )
1178 NorthEast = true;
1179 else if( xmlAttribute->GetValue() == wxT( "NW" ) )
1180 NorthWest = true;
1181 else if( xmlAttribute->GetValue() == wxT( "SE" ) )
1182 SouthEast = true;
1183 else if( xmlAttribute->GetValue() == wxT( "SW" ) )
1184 SouthWest = true;
1185 else
1186 WARN_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), wxT( "EXITS" ) );
1187 }
1188
1189 CheckNoChildNodes( aNode );
1190}
1191
1192
1194{
1195 wxASSERT( aNode->GetName() == wxT( "PAD" ) );
1196
1197 ID = GetXmlAttributeIDLong( aNode, 0 );
1198 PadCodeID = GetXmlAttributeIDString( aNode, 2 );
1199 Side = GetPadSide( GetXmlAttributeIDString( aNode, 3 ) );
1200
1201 XNODE* cNode = aNode->GetChildren();
1202 wxString location = wxString::Format( wxT( "PAD %ld" ), ID );
1203
1204 if( !cNode )
1205 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), location );
1206
1207 for( ; cNode; cNode = cNode->GetNext() )
1208 {
1209 wxString cNodeName = cNode->GetName();
1210
1211 if( cNodeName == wxT( "ORIENT" ) )
1212 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1213 else if( cNodeName == wxT( "FIRSTPAD" ) )
1214 FirstPad = true;
1215 else if( cNodeName == wxT( "EXITS" ) )
1216 Exits.Parse( cNode, aContext );
1217 else if( cNodeName == wxT( "PADIDENTIFIER" ) )
1218 Identifier = GetXmlAttributeIDString( cNode, 0 );
1219 else if( cNodeName == wxT( "PCBONLYPAD" ) )
1220 PCBonlyPad = true;
1221 else if( cNodeName == wxT( "PT" ) )
1222 Position.Parse( cNode, aContext );
1223 else
1225 }
1226}
1227
1228
1230{
1231 wxASSERT( aNode->GetName() == wxT( "DIMARROW" ) );
1232 bool arrowStyleInitialised = false;
1233 bool upperAngleInitialised = false;
1234 bool lowerAngleInitialised = false;
1235
1236 ArrowLength = GetXmlAttributeIDLong( aNode, 3 );
1237
1238 XNODE* cNode = aNode->GetChildren();
1239
1240
1241 for( ; cNode; cNode = cNode->GetNext() )
1242 {
1243 wxString cNodeName = cNode->GetName();
1244
1245 if( cNodeName == wxT( "ARROWSTYLE" ) )
1246 {
1247 wxString arrowStyleStr = GetXmlAttributeIDString( cNode, 0 );
1248 arrowStyleInitialised = true;
1249
1250 if( arrowStyleStr == wxT( "DIMENSION_ARROWOPEN" ) )
1252 else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLOSED" ) )
1254 else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLEAR" ) )
1256 else if( arrowStyleStr == wxT( "DIMENSION_ARROWCLOSEDFILLED" ) )
1258 else
1259 WARN_UNKNOWN_PARAMETER_IO_ERROR( arrowStyleStr, cNodeName );
1260 }
1261 else if( cNodeName == wxT( "ARROWANGLEA" ) )
1262 {
1263 UpperAngle = GetXmlAttributeIDLong( cNode, 0 );
1264 upperAngleInitialised = true;
1265 }
1266 else if( cNodeName == wxT( "ARROWANGLEB" ) )
1267 {
1268 LowerAngle = GetXmlAttributeIDLong( cNode, 0 );
1269 lowerAngleInitialised = true;
1270 }
1271 else
1272 {
1273 WARN_UNKNOWN_PARAMETER_IO_ERROR( cNodeName, wxT( "DIMARROW" ) );
1274 }
1275 }
1276
1277 if( !arrowStyleInitialised )
1278 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWSTYLE" ), wxT( "DIMARROW" ) );
1279
1280 if( !upperAngleInitialised )
1281 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWANGLEA" ), wxT( "DIMARROW" ) );
1282
1283 if( !lowerAngleInitialised )
1284 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "ARROWANGLEB" ), wxT( "DIMARROW" ) );
1285}
1286
1287
1289 PARSER_CONTEXT* aContext )
1290{
1291 wxASSERT( aNode->GetName() == wxT( "DIMTEXT" ) );
1292
1293 TextGap = GetXmlAttributeIDLong( aNode, 1 );
1294 TextOffset = GetXmlAttributeIDLong( aNode, 2 );
1295
1296 XNODE* cNode = aNode->GetChildren();
1297
1298 if( !cNode )
1299 {
1300 WARN_UNKNOWN_NODE_IO_ERROR( wxT( "(empty)" ), wxT( "DIMTEXT" ) );
1301 return;
1302 }
1303
1304 if( cNode->GetName() != wxT( "TXTSTYLE" ) )
1305 {
1306 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "DIMTEXT" ) );
1307 return;
1308 }
1309
1310 wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
1311
1312 if( styleStr == wxT( "DIMENSION_INTERNAL" ) )
1314 else if( styleStr == wxT( "DIMENSION_EXTERNAL" ) )
1316 else
1317 WARN_UNKNOWN_PARAMETER_IO_ERROR( styleStr, wxT( "TXTSTYLE" ) );
1318
1319 CheckNoNextNodes( cNode );
1320}
1321
1322
1324 PARSER_CONTEXT* aContext )
1325{
1326 wxASSERT( aNode->GetName() == wxT( "EXTLINE" ) );
1327
1328 LineCodeID = GetXmlAttributeIDString( aNode, 0 );
1329 Overshoot = GetXmlAttributeIDLong( aNode, 3 );
1330 Offset = GetXmlAttributeIDLong( aNode, 4 );
1331
1332 XNODE* cNode = aNode->GetChildren();
1333 int noOfPoints = 0;
1334
1335 for( ; cNode; cNode = cNode->GetNext() )
1336 {
1337 wxString cNodeName = cNode->GetName();
1338
1339 if( noOfPoints < 2 && cNodeName == wxT( "PT" ) )
1340 {
1341 ++noOfPoints;
1342
1343 if( noOfPoints == 1 )
1344 Start.Parse( cNode, aContext );
1345 else
1346 End.Parse( cNode, aContext );
1347 }
1348 else if( cNodeName == wxT( "SUPPRESSFIRST" ) )
1349 {
1350 SuppressFirst = true;
1351 }
1352 else
1353 {
1354 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "EXTLINE" ) );
1355 }
1356 }
1357
1358 if( noOfPoints != 2 )
1359 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), wxT( "EXTLINE" ) );
1360}
1361
1362
1364{
1365 if( aNode->GetName() == wxT( "LEADERLINE" ) || aNode->GetName() == wxT( "LINEARLINE" )
1366 || aNode->GetName() == wxT( "ANGULARLINE" ) )
1367 {
1368 return true;
1369 }
1370 else
1371 {
1372 return false;
1373 }
1374}
1375
1376
1378{
1379 wxASSERT( IsLine( aNode ) );
1380
1381 if( aNode->GetName() == wxT( "LINEARLINE" ) )
1382 Type = TYPE::LINEARLINE;
1383 else if( aNode->GetName() == wxT( "LEADERLINE" ) )
1384 Type = TYPE::LEADERLINE;
1385 else if( aNode->GetName() == wxT( "ANGULARLINE" ) )
1386 Type = TYPE::ANGULARLINE;
1387 else
1388 wxASSERT_MSG( true, wxT( "Not a valid type. What happened to the node Name?" ) );
1389
1390 LineCodeID = GetXmlAttributeIDString( aNode, 0 );
1391
1392 if( Type == TYPE::LEADERLINE )
1393 {
1396 }
1397
1398 XNODE* cNode = aNode->GetChildren();
1399 int noOfPoints = 0;
1400 int requiredNoOfPoints = 2;
1401
1402 if( Type == TYPE::ANGULARLINE )
1403 requiredNoOfPoints = 3;
1404
1405 for( ; cNode; cNode = cNode->GetNext() )
1406 {
1407 wxString cNodeName = cNode->GetName();
1408
1409 if( cNodeName == wxT( "DIMLINETYPE" ) )
1410 {
1411 wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
1412
1413 if( styleStr == wxT( "DIMENSION_INTERNAL" ) )
1415 else if( styleStr == wxT( "DIMENSION_EXTERNAL" ) )
1417 else
1418 WARN_UNKNOWN_PARAMETER_IO_ERROR( styleStr, cNodeName );
1419 }
1420 else if( noOfPoints < requiredNoOfPoints && cNodeName == wxT( "PT" ) )
1421 {
1422 ++noOfPoints;
1423
1424 if( noOfPoints == 1 )
1425 Start.Parse( cNode, aContext );
1426 else if( noOfPoints == 2 )
1427 End.Parse( cNode, aContext );
1428 else
1429 Centre.Parse( cNode, aContext );
1430 }
1431 else if( Type == TYPE::LEADERLINE && cNodeName == wxT( "LEADERANG" ) )
1432 {
1433 LeaderAngle = GetXmlAttributeIDLong( cNode, 0 );
1434 }
1435 else
1436 {
1437 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1438 }
1439 }
1440
1441 if( noOfPoints != requiredNoOfPoints )
1442 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
1443}
1444
1445
1447{
1448 if( aNode->GetName() == wxT( "LINEARDIM" ) || aNode->GetName() == wxT( "LEADERDIM" )
1449 || aNode->GetName() == wxT( "ANGLEDIM" ) )
1450 {
1451 return true;
1452 }
1453 else
1454 {
1455 return false;
1456 }
1457}
1458
1459
1461{
1462 wxASSERT( IsDimension( aNode ) );
1463
1464 std::map<wxString, TYPE> typeMap = { { wxT( "LINEARDIM" ), TYPE::LINEARDIM },
1465 { wxT( "LEADERDIM" ), TYPE::LEADERDIM }, { wxT( "ANGLEDIM" ), TYPE::ANGLEDIM } };
1466
1467 //make sure aNode is valid TYPE
1468 wxASSERT_MSG( typeMap.find( aNode->GetName() ) != typeMap.end(),
1469 wxT( "Not a valid type. What happened to the node Name?" ) );
1470
1471 Type = typeMap[aNode->GetName()];
1472 LayerID = GetXmlAttributeIDString( aNode, 1 );
1473 wxString subTypeStr = GetXmlAttributeIDString( aNode, 2 );
1474
1475 std::map<wxString, SUBTYPE> subTypeMap = {
1476 { wxT( "DIMENSION_ORTHOGONAL" ), SUBTYPE::ORTHOGONAL },
1477 { wxT( "DIMENSION_DIRECT" ), SUBTYPE::DIRECT },
1478 { wxT( "DIMENSION_ANGLED" ), SUBTYPE::ANGLED },
1479 { wxT( "DIMENSION_DIAMETER" ), SUBTYPE::DIAMETER },
1480 { wxT( "DIMENSION_RADIUS" ), SUBTYPE::RADIUS },
1481 { wxT( "DIMENSION_ANGULAR" ), SUBTYPE::ANGULAR } };
1482
1483 if( subTypeMap.find( subTypeStr ) == subTypeMap.end() )
1484 {
1485 WARN_UNKNOWN_PARAMETER_IO_ERROR( subTypeStr, aNode->GetName() );
1487 }
1488 else
1489 {
1490 Subtype = subTypeMap[subTypeStr];
1491 }
1492 Precision = GetXmlAttributeIDLong( aNode, 3 );
1493
1494 XNODE* cNode = aNode->GetChildren();
1495
1496 bool idParsed = false;
1497 bool unitsParsed = false; //UNITS or ANGUNITS
1498 bool arrowParsed = false;
1499 bool textFormatParsed = false;
1500 bool extLineParsed = false;
1501 bool lineParsed = false;
1502 bool textParsed = false;
1503
1504 for( ; cNode; cNode = cNode->GetNext() )
1505 {
1506 wxString cNodeName = cNode->GetName();
1507
1508 if( !idParsed && cNodeName == wxT( "DIMREF" ) )
1509 {
1510 ID = GetXmlAttributeIDString( cNode, 0 );
1511 idParsed = true;
1512 }
1513 else if( !unitsParsed && cNodeName == wxT( "UNITS" ) )
1514 {
1515 LinearUnits = ParseUnits( cNode );
1516 unitsParsed = true;
1517 }
1518 else if( !unitsParsed && cNodeName == wxT( "ANGUNITS" ) )
1519 {
1520 AngularUnits = ParseAngunits( cNode );
1521 unitsParsed = true;
1522 }
1523 else if( !arrowParsed && cNodeName == wxT( "DIMARROW" ) )
1524 {
1525 Arrow.Parse( cNode, aContext );
1526 arrowParsed = true;
1527 }
1528 else if( !textFormatParsed && cNodeName == wxT( "DIMTEXT" ) )
1529 {
1530 TextParams.Parse( cNode, aContext );
1531 textFormatParsed = true;
1532 }
1533 else if( !extLineParsed && cNodeName == wxT( "EXTLINE" ) )
1534 {
1535 ExtensionLineParams.Parse( cNode, aContext );
1536 extLineParsed = true;
1537 }
1538 else if( !lineParsed && LINE::IsLine( cNode ) )
1539 {
1540 Line.Parse( cNode, aContext );
1541 lineParsed = true;
1542 }
1543 else if( !textParsed && cNodeName == wxT( "TEXT" ) )
1544 {
1545 // Do not parse the fields in dimension text (will be done when loading, if required)
1546 Text.Parse( cNode, aContext, false );
1547 textParsed = true;
1548 }
1549 else if( cNodeName == wxT( "FIX" ) )
1550 {
1551 Fixed = true;
1552 }
1553 else if( cNodeName == wxT( "GROUPREF" ) )
1554 {
1555 GroupID = GetXmlAttributeIDString( cNode, 0 );
1556 }
1557 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1558 {
1559 ReuseBlockRef.Parse( cNode, aContext );
1560 }
1561 else
1562 {
1563 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1564 }
1565 }
1566}
1567
1568
1570{
1571 wxASSERT( aNode->GetName() == wxT( "SYMDEF" ) );
1572
1573 ParseIdentifiers( aNode, aContext );
1574
1575 wxString rest;
1576
1577 if( ReferenceName.StartsWith( wxT( "JUMPERNF" ), &rest ) )
1579 else if( ReferenceName.StartsWith( wxT( "STARPOINTNF" ), &rest ) )
1581 else if( ReferenceName == wxT( "TESTPOINT" ) )
1583 else
1585
1586 XNODE* cNode = aNode->GetChildren();
1587
1588 for( ; cNode; cNode = cNode->GetNext() )
1589 {
1590 wxString cNodeName = cNode->GetName();
1591
1592 if( ParseSubNode( cNode, aContext ) )
1593 {
1594 continue;
1595 }
1596 else if( cNodeName == wxT( "SYMHEIGHT" ) )
1597 {
1598 SymHeight = GetXmlAttributeIDLong( cNode, 0 );
1599 }
1600 else if( cNodeName == wxT( "COMPCOPPER" ) )
1601 {
1602 COMPONENT_COPPER compcopper;
1603 compcopper.Parse( cNode, aContext );
1604 ComponentCoppers.push_back( compcopper );
1605 }
1606 else if( cNodeName == wxT( "COMPAREA" ) )
1607 {
1608 COMPONENT_AREA area;
1609 area.Parse( cNode, aContext );
1610 ComponentAreas.insert( std::make_pair( area.ID, area ) );
1611 }
1612 else if( cNodeName == wxT( "PAD" ) )
1613 {
1615 pad.Parse( cNode, aContext );
1616 ComponentPads.insert( std::make_pair( pad.ID, pad ) );
1617 }
1618 else if( cNodeName == wxT( "DIMENSIONS" ) )
1619 {
1620 XNODE* dimensionNode = cNode->GetChildren();
1621
1622 for( ; dimensionNode; dimensionNode = dimensionNode->GetNext() )
1623 {
1624 if( DIMENSION::IsDimension( dimensionNode ) )
1625 {
1626 DIMENSION dim;
1627 dim.Parse( dimensionNode, aContext );
1628 Dimensions.insert( std::make_pair( dim.ID, dim ) );
1629 }
1630 else
1631 {
1632 WARN_UNKNOWN_NODE_IO_ERROR( dimensionNode->GetName(), cNodeName );
1633 }
1634 }
1635 }
1636 else
1637 {
1638 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1639 }
1640 }
1641
1642 if( !Stub && ( Origin.x == UNDEFINED_VALUE || Origin.y == UNDEFINED_VALUE ) )
1643 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
1644}
1645
1646
1648{
1649 wxASSERT( aNode->GetName() == wxT( "LIBRARY" ) );
1650
1651 XNODE* cNode = aNode->GetChildren();
1652
1653 for( ; cNode; cNode = cNode->GetNext() )
1654 {
1655 wxString cNodeName = cNode->GetName();
1656
1657 if( cNodeName == wxT( "SYMDEF" ) )
1658 {
1659 SYMDEF_PCB symdef;
1660 symdef.Parse( cNode, aContext );
1661 ComponentDefinitions.insert( std::make_pair( symdef.ID, symdef ) );
1662 }
1663 else if( cNodeName == wxT( "HIERARCHY" ) )
1664 {
1665 // Ignore for now
1666 //
1667 // This node doesn't have any equivalent in KiCad so for now we ignore it. In
1668 // future, we could parse it in detail, to obtain the tree-structure of
1669 // footprints in a cadstar library
1670 }
1671 else
1672 {
1673 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1674 }
1675
1676 aContext->CheckPointCallback();
1677 }
1678}
1679
1680
1682{
1683 wxASSERT( aNode->GetName() == wxT( "BOARD" ) );
1684
1685 ID = GetXmlAttributeIDString( aNode, 0 );
1686 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1687
1688 XNODE* cNode = aNode->GetChildren();
1689 bool shapeIsInitialised = false; // Stop more than one Shape Object
1690 wxString location = wxString::Format( wxT( "BOARD %s" ), ID );
1691
1692 if( !cNode )
1693 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1694
1695 for( ; cNode; cNode = cNode->GetNext() )
1696 {
1697 wxString cNodeName = cNode->GetName();
1698
1699 if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
1700 {
1701 Shape.Parse( cNode, aContext );
1702 shapeIsInitialised = true;
1703 }
1704 else if( cNodeName == wxT( "ATTR" ) )
1705 {
1706 ATTRIBUTE_VALUE attr;
1707 attr.Parse( cNode, aContext );
1708 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1709 }
1710 else if( cNodeName == wxT( "FIX" ) )
1711 {
1712 Fixed = true;
1713 }
1714 else if( cNodeName == wxT( "GROUPREF" ) )
1715 {
1716 GroupID = GetXmlAttributeIDString( cNode, 0 );
1717 }
1718 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1719 {
1720 ReuseBlockRef.Parse( cNode, aContext );
1721 }
1722 else
1723 {
1725 }
1726 }
1727}
1728
1729
1731{
1732 wxASSERT( aNode->GetName() == wxT( "AREA" ) );
1733
1734 ID = GetXmlAttributeIDString( aNode, 0 );
1735 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1736 Name = GetXmlAttributeIDString( aNode, 2 );
1737 LayerID = GetXmlAttributeIDString( aNode, 4 );
1738
1739 XNODE* cNode = aNode->GetChildren();
1740 bool shapeIsInitialised = false; // Stop more than one Shape Object
1741 wxString location = wxString::Format( wxT( "AREA %s" ), ID );
1742
1743 if( !cNode )
1744 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1745
1746 for( ; cNode; cNode = cNode->GetNext() )
1747 {
1748 wxString cNodeName = cNode->GetName();
1749
1750 if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
1751 {
1752 Shape.Parse( cNode, aContext );
1753 shapeIsInitialised = true;
1754 }
1755 else if( cNodeName == wxT( "FIX" ) )
1756 {
1757 Fixed = true;
1758 }
1759 else if( cNodeName == wxT( "USAGE" ) )
1760 {
1761 wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
1762
1763 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1764 {
1765 if( !IsValidAttribute( xmlAttribute ) )
1766 continue;
1767
1768 if( xmlAttribute->GetValue() == wxT( "PLACEMENT" ) )
1769 Placement = true;
1770 else if( xmlAttribute->GetValue() == wxT( "ROUTING" ) )
1771 Routing = true;
1772 else if( xmlAttribute->GetValue() == wxT( "KEEPOUT" ) )
1773 Keepout = true;
1774 else if( xmlAttribute->GetValue() == wxT( "NO_TRACKS" ) )
1775 NoTracks = true;
1776 else if( xmlAttribute->GetValue() == wxT( "NO_VIAS" ) )
1777 NoVias = true;
1778 else
1779 WARN_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), location );
1780 }
1781
1782 CheckNoChildNodes( cNode );
1783 }
1784 else if( cNodeName == wxT( "AREAHEIGHT" ) )
1785 {
1786 AreaHeight = GetXmlAttributeIDLong( cNode, 0 );
1787 }
1788 else if( cNodeName == wxT( "GROUPREF" ) )
1789 {
1790 GroupID = GetXmlAttributeIDString( cNode, 0 );
1791 }
1792 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1793 {
1794 ReuseBlockRef.Parse( cNode, aContext );
1795 }
1796 else if( cNodeName == wxT( "ATTR" ) )
1797 {
1798 ATTRIBUTE_VALUE attr;
1799 attr.Parse( cNode, aContext );
1800 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1801 }
1802 else
1803 {
1805 }
1806 }
1807}
1808
1809
1811{
1812 wxASSERT( aNode->GetName() == wxT( "PINATTR" ) );
1813
1814 Pin = GetXmlAttributeIDLong( aNode, 0 );
1815
1816 XNODE* cNode = aNode->GetChildren();
1817
1818 for( ; cNode; cNode = cNode->GetNext() )
1819 {
1820 wxString cNodeName = cNode->GetName();
1821
1822 if( cNodeName == wxT( "ATTR" ) )
1823 {
1824 ATTRIBUTE_VALUE attrVal;
1825 attrVal.Parse( cNode, aContext );
1826 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
1827 }
1828 else if( cNodeName == wxT( "TESTLAND" ) )
1829 {
1831 }
1832 else
1833 {
1834 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1835 }
1836 }
1837}
1838
1839
1841{
1842 wxASSERT( aNode->GetName() == wxT( "PADEXCEPTION" ) );
1843
1844 ID = GetXmlAttributeIDLong( aNode, 0 );
1845
1846 XNODE* cNode = aNode->GetChildren();
1847
1848 for( ; cNode; cNode = cNode->GetNext() )
1849 {
1850 wxString cNodeName = cNode->GetName();
1851
1852 if( cNodeName == wxT( "PADCODEREF" ) )
1853 {
1854 PadCode = GetXmlAttributeIDString( cNode, 0 );
1855 }
1856 else if( cNodeName == wxT( "EXITS" ) )
1857 {
1858 OverrideExits = true;
1859 Exits.Parse( cNode, aContext );
1860 }
1861 else if( cNodeName == wxT( "SIDE" ) )
1862 {
1863 OverrideSide = true;
1864 Side = GetPadSide( GetXmlAttributeIDString( cNode, 0 ) );
1865 }
1866 else if( cNodeName == wxT( "ORIENT" ) )
1867 {
1868 OverrideOrientation = true;
1869 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1870 }
1871 else
1872 {
1873 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1874 }
1875 }
1876}
1877
1878
1880{
1881 wxASSERT( aNode->GetName() == wxT( "COMP" ) );
1882
1883 ID = GetXmlAttributeIDString( aNode, 0 );
1884 Name = GetXmlAttributeIDString( aNode, 1 );
1885 PartID = GetXmlAttributeIDString( aNode, 2 );
1886 SymdefID = GetXmlAttributeIDString( aNode, 3 );
1887
1888 XNODE* cNode = aNode->GetChildren();
1889 bool originParsed = false;
1890
1891 for( ; cNode; cNode = cNode->GetNext() )
1892 {
1893 wxString cNodeName = cNode->GetName();
1894
1895 if( !originParsed && cNodeName == wxT( "PT" ) )
1896 {
1897 Origin.Parse( cNode, aContext );
1898 originParsed = true;
1899 }
1900 else if( cNodeName == wxT( "GROUPREF" ) )
1901 {
1902 GroupID = GetXmlAttributeIDString( cNode, 0 );
1903 }
1904 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1905 {
1906 ReuseBlockRef.Parse( cNode, aContext );
1907 }
1908 else if( cNodeName == wxT( "TESTPOINT" ) )
1909 {
1910 TestPoint = true;
1911 }
1912 else if( cNodeName == wxT( "FIX" ) )
1913 {
1914 Fixed = true;
1915 }
1916 else if( cNodeName == wxT( "MIRROR" ) )
1917 {
1918 Mirror = true;
1919 }
1920 else if( cNodeName == wxT( "READABILITY" ) )
1921 {
1922 Readability = ParseReadability( cNode );
1923 }
1924 else if( cNodeName == wxT( "ORIENT" ) )
1925 {
1926 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1927 }
1928 else if( cNodeName == wxT( "VCOMPMASTER" ) )
1929 {
1931 VariantID = GetXmlAttributeIDString( cNode, 1 );
1932 }
1933 else if( cNodeName == wxT( "TEXTLOC" ) )
1934 {
1935 TEXT_LOCATION textloc;
1936 textloc.Parse( cNode, aContext );
1937 TextLocations.insert( std::make_pair( textloc.AttributeID, textloc ) );
1938 }
1939 else if( cNodeName == wxT( "ATTR" ) )
1940 {
1941 ATTRIBUTE_VALUE attrVal;
1942 attrVal.Parse( cNode, aContext );
1943 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
1944 }
1945 else if( cNodeName == wxT( "PINATTR" ) )
1946 {
1947 PIN_ATTRIBUTE pinAttr;
1948 pinAttr.Parse( cNode, aContext );
1949 PinAttributes.insert( std::make_pair( pinAttr.Pin, pinAttr ) );
1950 }
1951 else if( cNodeName == wxT( "COMPPINLABEL" ) )
1952 {
1954 wxString pinLabel = GetXmlAttributeIDString( cNode, 1 );
1955 PinLabels.insert( std::make_pair( pinID, pinLabel ) );
1956 }
1957 else if( cNodeName == wxT( "PADEXCEPTION" ) )
1958 {
1959 PADEXCEPTION padExcept;
1960 padExcept.Parse( cNode, aContext );
1961 PadExceptions.insert( std::make_pair( padExcept.ID, padExcept ) );
1962 }
1963 else
1964 {
1965 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1966 }
1967 }
1968
1969 if( !originParsed )
1970 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
1971}
1972
1973
1975 XNODE* aNode )
1976{
1977 wxASSERT( aNode->GetName() == wxT( "TESTLAND" ) );
1978
1979 wxString side = GetXmlAttributeIDString( aNode, 0 );
1980
1981 if( side == wxT( "MIN_SIDE" ) )
1982 return TESTLAND_SIDE::MIN;
1983 else if( side == wxT( "MAX_SIDE" ) )
1984 return TESTLAND_SIDE::MAX;
1985 else if( side == wxT( "BOTH_SIDES" ) )
1986 return TESTLAND_SIDE::BOTH;
1987 else
1988 WARN_UNKNOWN_PARAMETER_IO_ERROR( side, aNode->GetName() );
1989
1990 return TESTLAND_SIDE::NONE;
1991}
1992
1993
1995{
1996 wxASSERT( aNode->GetName() == wxT( "TRUNK" ) );
1997
1998 ID = GetXmlAttributeIDString( aNode, 0 );
1999 Definition = GetXmlAttributeIDString( aNode, 1 );
2000}
2001
2002
2004{
2005 wxASSERT( aNode->GetName() == wxT( "PIN" ) );
2006
2007 ID = GetXmlAttributeIDString( aNode, 0 );
2009 PadID = GetXmlAttributeIDLong( aNode, 2 );
2010 CheckNoChildNodes( aNode );
2011}
2012
2013
2015 PARSER_CONTEXT* aContext )
2016{
2017 ParseIdentifiers( aNode, aContext );
2018 XNODE* cNode = aNode->GetChildren();
2019
2020 for( ; cNode; cNode = cNode->GetNext() )
2021 {
2022 if( ParseSubNode( cNode, aContext ) )
2023 continue;
2024 else if( cNode->GetName() == wxT( "TRUNKREF" ) )
2025 TrunkID = GetXmlAttributeIDString( cNode, 0 );
2026 else
2027 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2028 }
2029}
2030
2031
2033{
2034 wxASSERT( aNode->GetName() == wxT( "VIA" ) );
2035
2036 ID = GetXmlAttributeIDString( aNode, 0 );
2037 ViaCodeID = GetXmlAttributeIDString( aNode, 1 );
2039
2040 XNODE* cNode = aNode->GetChildren();
2041
2042 for( ; cNode; cNode = cNode->GetNext() )
2043 {
2044 wxString cNodeName = cNode->GetName();
2045
2046 if( cNodeName == wxT( "PT" ) )
2047 Location.Parse( cNode, aContext );
2048 else if( cNodeName == wxT( "FIX" ) )
2049 Fixed = true;
2050 else if( cNodeName == wxT( "GROUPREF" ) )
2051 GroupID = GetXmlAttributeIDString( cNode, 0 );
2052 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2053 ReuseBlockRef.Parse( cNode, aContext );
2054 else if( cNodeName == wxT( "TESTLAND" ) )
2056 else if( cNode->GetName() == wxT( "TRUNKREF" ) )
2057 TrunkID = GetXmlAttributeIDString( cNode, 0 );
2058 else
2059 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2060 }
2061}
2062
2063
2065 PARSER_CONTEXT* aContext )
2066{
2067 wxASSERT( aNode->GetName() == wxT( "COPTERM" ) );
2068
2069 ID = GetXmlAttributeIDString( aNode, 0 );
2070 CopperID = GetXmlAttributeIDString( aNode, 1 );
2072}
2073
2074
2076 PARSER_CONTEXT* aContext )
2077{
2078 XNODE* prevNode = aNode;
2079 XNODE* nextNode = aNode->GetNext();
2080 bool vertexParsed = false;
2081
2082 if( aNode->GetName() == wxT( "ROUTEWIDTH" ) )
2083 {
2084 RouteWidth = GetXmlAttributeIDLong( aNode, 0 );
2085 }
2086 else
2087 {
2088 // CADSTAR Revision 7 routes may omit ROUTEWIDTH and start directly with the vertex; the
2089 // width is derived later from the connection's route code.
2090 wxASSERT( VERTEX::IsVertex( aNode ) );
2091 RouteWidthIsExplicit = false;
2092 Vertex.Parse( aNode, aContext );
2093 vertexParsed = true;
2094 }
2095
2096 for( ; nextNode; nextNode = nextNode->GetNext() )
2097 {
2098 if( nextNode->GetName() == wxT( "FIX" ) )
2099 {
2100 Fixed = true;
2101 }
2102 else if( nextNode->GetName() == wxT( "TDROPATSTART" ) )
2103 {
2104 TeardropAtStart = true;
2106 }
2107 else if( nextNode->GetName() == wxT( "TDROPATEND" ) )
2108 {
2109 TeardropAtEnd = true;
2111 }
2112 else if( VERTEX::IsVertex( nextNode ) )
2113 {
2114 // A ROUTEWIDTH record holds a single vertex. Encountering another one (with no
2115 // intervening ROUTEWIDTH) marks the start of the next Revision 7 vertex record.
2116 if( vertexParsed )
2117 return prevNode;
2118
2119 Vertex.Parse( nextNode, aContext );
2120 vertexParsed = true;
2121 }
2122 else if( nextNode->GetName() == wxT( "ROUTEWIDTH" ) )
2123 {
2124 return prevNode;
2125 }
2126 else
2127 {
2128 WARN_UNKNOWN_NODE_IO_ERROR( nextNode->GetName(), wxT( "ROUTE" ) );
2129 }
2130
2131 prevNode = nextNode;
2132 }
2133
2134 return prevNode;
2135}
2136
2137
2139{
2140 wxASSERT( aNode->GetName() == wxT( "ROUTE" ) );
2141
2142 LayerID = GetXmlAttributeIDString( aNode, 0 );
2143
2144 //Parse child nodes
2145 XNODE* cNode = aNode->GetChildren();
2146 bool startPointParsed = false;
2147
2148 for( ; cNode; cNode = cNode->GetNext() )
2149 {
2150 wxString cNodeName = cNode->GetName();
2151
2152 if( !startPointParsed && cNodeName == wxT( "PT" ) )
2153 {
2154 startPointParsed = true;
2155 StartPoint.Parse( cNode, aContext );
2156 }
2157 else if( cNodeName == wxT( "ROUTEWIDTH" ) || VERTEX::IsVertex( cNode ) )
2158 {
2159 // A route vertex normally starts with ROUTEWIDTH, but CADSTAR Revision 7 files may
2160 // omit it and start directly with the vertex; ROUTE_VERTEX::Parse handles both and
2161 // consumes any trailing FIX/teardrop metadata, returning the last node it consumed.
2162 ROUTE_VERTEX rtVert;
2163 cNode = rtVert.Parse( cNode, aContext );
2164 RouteVertices.push_back( rtVert );
2165
2166 assert( cNode != nullptr );
2167 }
2168 else
2169 {
2170 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "ROUTE" ) );
2171 }
2172 }
2173}
2174
2175
2177 PARSER_CONTEXT* aContext )
2178{
2179 ParseIdentifiers( aNode, aContext );
2180
2181 //Parse child nodes
2182 XNODE* cNode = aNode->GetChildren();
2183 bool routeParsed = false; //assume only one route per connection
2184
2185 for( ; cNode; cNode = cNode->GetNext() )
2186 {
2187 wxString cNodeName = cNode->GetName();
2188
2189 if( ParseSubNode( cNode, aContext ) )
2190 {
2191 continue;
2192 }
2193 else if( !Unrouted && !routeParsed && cNodeName == wxT( "ROUTE" ) )
2194 {
2195 Route.Parse( cNode, aContext );
2196 routeParsed = true;
2197 }
2198 else if( !routeParsed && cNodeName == wxT( "UNROUTE" ) )
2199 {
2200 Unrouted = true;
2202 }
2203 else if( cNode->GetName() == wxT( "TRUNKREF" ) )
2204 {
2205 TrunkID = GetXmlAttributeIDString( cNode, 0 );
2206 }
2207 else
2208 {
2209 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "CONN" ) );
2210 }
2211 }
2212}
2213
2214
2216{
2217 ParseIdentifiers( aNode, aContext );
2218
2219 //Parse child nodes
2220 XNODE* cNode = aNode->GetChildren();
2221
2222 for( ; cNode; cNode = cNode->GetNext() )
2223 {
2224 wxString cNodeName = cNode->GetName();
2225
2226 if( cNodeName == wxT( "JPT" ) )
2227 {
2228 JUNCTION_PCB jpt;
2229 jpt.Parse( cNode, aContext );
2230 Junctions.insert( std::make_pair( jpt.ID, jpt ) );
2231 }
2232 else if( ParseSubNode( cNode, aContext ) )
2233 {
2234 continue;
2235 }
2236 else if( cNodeName == wxT( "PIN" ) )
2237 {
2238 PIN pin;
2239 pin.Parse( cNode, aContext );
2240 Pins.insert( std::make_pair( pin.ID, pin ) );
2241 }
2242 else if( cNodeName == wxT( "VIA" ) )
2243 {
2244 VIA via;
2245 via.Parse( cNode, aContext );
2246 Vias.insert( std::make_pair( via.ID, via ) );
2247 }
2248 else if( cNodeName == wxT( "COPTERM" ) )
2249 {
2250 COPPER_TERMINAL cterm;
2251 cterm.Parse( cNode, aContext );
2252 CopperTerminals.insert( std::make_pair( cterm.ID, cterm ) );
2253 }
2254 else if( cNodeName == wxT( "CONN" ) )
2255 {
2256 CONNECTION_PCB conn;
2257 conn.Parse( cNode, aContext );
2258 Connections.push_back( conn );
2259 }
2260 else
2261 {
2262 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "NET" ) );
2263 }
2264 }
2265}
2266
2267
2269{
2270 wxASSERT( aNode->GetName() == wxT( "POURING" ) );
2271
2275 SliverWidth = GetXmlAttributeIDLong( aNode, 3 );
2279
2280 wxString MinIsolCopStr = GetXmlAttributeIDString( aNode, 7 );
2281
2282 if( MinIsolCopStr == wxT( "NONE" ) )
2284 else
2286
2287 wxString MinDisjCopStr = GetXmlAttributeIDString( aNode, 8 );
2288
2289 if( MinDisjCopStr == wxT( "NONE" ) )
2291 else
2293
2294 XNODE* cNode = aNode->GetChildren();
2295
2296 for( ; cNode; cNode = cNode->GetNext() )
2297 {
2298 wxString cNodeName = cNode->GetName();
2299
2300 if( cNodeName == wxT( "NOPINRELIEF" ) )
2301 {
2302 ThermalReliefOnPads = false;
2303 }
2304 else if( cNodeName == wxT( "NOVIARELIEF" ) )
2305 {
2306 ThermalReliefOnVias = false;
2307 }
2308 else if( cNodeName == wxT( "IGNORETRN" ) )
2309 {
2310 AllowInNoRouting = true;
2311 }
2312 else if( cNodeName == wxT( "BOXPINS" ) )
2313 {
2314 BoxIsolatedPins = true;
2315 }
2316 else if( cNodeName == wxT( "REGENERATE" ) )
2317 {
2318 AutomaticRepour = true;
2319 }
2320 else if( cNodeName == wxT( "AUTOROUTETARGET" ) )
2321 {
2322 TargetForAutorouting = true;
2323 }
2324 else if( cNodeName == wxT( "THERMALCUTOUT" ) )
2325 {
2327 }
2328 else if( cNodeName == wxT( "FILLED" ) )
2329 {
2331 }
2332 else if( cNodeName == wxT( "HATCHCODEREF" ) )
2333 {
2336 }
2337 else
2338 {
2339 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "POURING" ) );
2340 }
2341 }
2342}
2343
2344
2346{
2347 wxASSERT( aNode->GetName() == wxT( "TEMPLATE" ) );
2348
2349 ID = GetXmlAttributeIDString( aNode, 0 );
2350 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
2351 Name = GetXmlAttributeIDString( aNode, 2 );
2352 NetID = GetXmlAttributeIDString( aNode, 3 );
2353 LayerID = GetXmlAttributeIDString( aNode, 4 );
2354
2355 XNODE* cNode = aNode->GetChildren();
2356 bool shapeParsed = false;
2357 bool pouringParsed = false;
2358
2359 for( ; cNode; cNode = cNode->GetNext() )
2360 {
2361 wxString cNodeName = cNode->GetName();
2362
2363 if( !shapeParsed && SHAPE::IsShape( cNode ) )
2364 {
2365 Shape.Parse( cNode, aContext );
2366 shapeParsed = true;
2367 }
2368 else if( !pouringParsed && cNodeName == wxT( "POURING" ) )
2369 {
2370 Pouring.Parse( cNode, aContext );
2371 pouringParsed = true;
2372 }
2373 else if( cNodeName == wxT( "FIX" ) )
2374 {
2375 Fixed = true;
2376 }
2377 else if( cNodeName == wxT( "GROUPREF" ) )
2378 {
2379 GroupID = GetXmlAttributeIDString( cNode, 0 );
2380 }
2381 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2382 {
2383 ReuseBlockRef.Parse( cNode, aContext );
2384 }
2385 else if( cNodeName == wxT( "ATTR" ) )
2386 {
2387 ATTRIBUTE_VALUE attr;
2388 attr.Parse( cNode, aContext );
2389 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2390 }
2391 else
2392 {
2393 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEMPLATE" ) );
2394 }
2395 }
2396}
2397
2398
2400 PARSER_CONTEXT* aContext )
2401{
2402 wxASSERT( aNode->GetName() == wxT( "TERM" ) );
2403
2404 ID = GetXmlAttributeIDLong( aNode, 0 );
2405
2406 XNODE* cNode = aNode->GetChildren();
2407 bool locationParsed = false;
2408
2409 for( ; cNode; cNode = cNode->GetNext() )
2410 {
2411 wxString cNodeName = cNode->GetName();
2412
2413 if( !locationParsed && cNodeName == wxT( "PT" ) )
2414 {
2415 Location.Parse( cNode, aContext );
2416 locationParsed = true;
2417 }
2418 else if( cNodeName == wxT( "FIX" ) )
2419 {
2420 Fixed = true;
2421 }
2422 else
2423 {
2424 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2425 }
2426 }
2427}
2428
2429
2431{
2432 wxASSERT( aNode->GetName() == wxT( "NETREF" ) );
2433
2434 NetID = GetXmlAttributeIDString( aNode, 0 );
2435
2436 XNODE* cNode = aNode->GetChildren();
2437
2438 for( ; cNode; cNode = cNode->GetNext() )
2439 {
2440 wxString cNodeName = cNode->GetName();
2441
2442 if( cNodeName == wxT( "TERM" ) )
2443 {
2444 COPPER_TERM term;
2445 term.Parse( cNode, aContext );
2446 CopperTerminals.insert( std::make_pair( term.ID, term ) );
2447 }
2448 else if( cNodeName == wxT( "FIX" ) )
2449 {
2450 Fixed = true;
2451 }
2452 else
2453 {
2454 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "NETREF" ) );
2455 }
2456 }
2457}
2458
2459
2461{
2462 wxASSERT( aNode->GetName() == wxT( "COPPER" ) );
2463
2464 ID = GetXmlAttributeIDString( aNode, 0 );
2466 LayerID = GetXmlAttributeIDString( aNode, 2 );
2467
2468 XNODE* cNode = aNode->GetChildren();
2469 bool shapeParsed = false;
2470 bool netRefParsed = false;
2471
2472 for( ; cNode; cNode = cNode->GetNext() )
2473 {
2474 wxString cNodeName = cNode->GetName();
2475
2476 if( !shapeParsed && SHAPE::IsShape( cNode ) )
2477 {
2478 Shape.Parse( cNode, aContext );
2479 shapeParsed = true;
2480 }
2481 else if( !netRefParsed && cNodeName == wxT( "NETREF" ) )
2482 {
2483 NetRef.Parse( cNode, aContext );
2484 netRefParsed = true;
2485 }
2486 else if( cNodeName == wxT( "FIX" ) )
2487 {
2488 Fixed = true;
2489 }
2490 else if( cNodeName == wxT( "GROUPREF" ) )
2491 {
2492 GroupID = GetXmlAttributeIDString( cNode, 0 );
2493 }
2494 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2495 {
2496 ReuseBlockRef.Parse( cNode, aContext );
2497 }
2498 else if( cNodeName == wxT( "POURED" ) )
2499 {
2501 }
2502 else if( cNodeName == wxT( "ATTR" ) )
2503 {
2504 ATTRIBUTE_VALUE attr;
2505 attr.Parse( cNode, aContext );
2506 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2507 }
2508 else
2509 {
2510 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEMPLATE" ) );
2511 }
2512 }
2513}
2514
2515
2517{
2518 wxASSERT( aNode->GetName() == wxT( "DRILLTABLE" ) );
2519
2520 ID = GetXmlAttributeIDString( aNode, 0 );
2521 LayerID = GetXmlAttributeIDString( aNode, 1 );
2522
2523 XNODE* cNode = aNode->GetChildren();
2524 bool positionParsed = false;
2525
2526 for( ; cNode; cNode = cNode->GetNext() )
2527 {
2528 wxString cNodeName = cNode->GetName();
2529
2530 if( !positionParsed && cNodeName == wxT( "PT" ) )
2531 {
2532 Position.Parse( cNode, aContext );
2533 positionParsed = true;
2534 }
2535 else if( cNodeName == wxT( "ORIENT" ) )
2536 {
2537 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
2538 }
2539 else if( cNodeName == wxT( "MIRROR" ) )
2540 {
2541 Mirror = true;
2542 }
2543 else if( cNodeName == wxT( "FIX" ) )
2544 {
2545 Fixed = true;
2546 }
2547 else if( cNodeName == wxT( "READABILITY" ) )
2548 {
2549 Readability = ParseReadability( cNode );
2550 }
2551 else if( cNodeName == wxT( "GROUPREF" ) )
2552 {
2553 GroupID = GetXmlAttributeIDString( cNode, 0 );
2554 }
2555 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2556 {
2557 ReuseBlockRef.Parse( cNode, aContext );
2558 }
2559 else
2560 {
2561 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2562 }
2563 }
2564}
2565
2566
2568{
2569 wxASSERT( aNode->GetName() == wxT( "LAYOUT" ) );
2570
2571 XNODE* cNode = aNode->GetChildren();
2572 bool netSynchParsed = false;
2573 bool dimensionsParsed = false;
2574
2575 for( ; cNode; cNode = cNode->GetNext() )
2576 {
2577 wxString cNodeName = cNode->GetName();
2578
2579 if( !netSynchParsed && cNodeName == wxT( "NETSYNCH" ) )
2580 {
2581 std::map<wxString, NETSYNCH> netSynchMap = { { wxT( "WARNING" ), NETSYNCH::WARNING },
2582 { wxT( "FULL" ), NETSYNCH::FULL } };
2583
2584 wxString nsString = GetXmlAttributeIDString( cNode, 0 );
2585
2586 if( netSynchMap.find( nsString ) == netSynchMap.end() )
2587 {
2588 WARN_UNKNOWN_PARAMETER_IO_ERROR( nsString, aNode->GetName() );
2590 }
2591 else
2592 {
2593 NetSynch = netSynchMap[nsString];
2594 }
2595 netSynchParsed = true;
2596 }
2597 else if( cNodeName == wxT( "GROUP" ) )
2598 {
2599 GROUP group;
2600 group.Parse( cNode, aContext );
2601 Groups.insert( std::make_pair( group.ID, group ) );
2602 }
2603 else if( cNodeName == wxT( "REUSEBLOCK" ) )
2604 {
2605 REUSEBLOCK reuseblock;
2606 reuseblock.Parse( cNode, aContext );
2607 ReuseBlocks.insert( std::make_pair( reuseblock.ID, reuseblock ) );
2608 }
2609 else if( cNodeName == wxT( "BOARD" ) )
2610 {
2611 CADSTAR_BOARD board;
2612 board.Parse( cNode, aContext );
2613 Boards.insert( std::make_pair( board.ID, board ) );
2614 }
2615 else if( cNodeName == wxT( "FIGURE" ) )
2616 {
2617 FIGURE figure;
2618 figure.Parse( cNode, aContext );
2619 Figures.insert( std::make_pair( figure.ID, figure ) );
2620 }
2621 else if( cNodeName == wxT( "AREA" ) )
2622 {
2623 AREA area;
2624 area.Parse( cNode, aContext );
2625 Areas.insert( std::make_pair( area.ID, area ) );
2626 }
2627 else if( cNodeName == wxT( "COMP" ) )
2628 {
2630 comp.Parse( cNode, aContext );
2631 Components.insert( std::make_pair( comp.ID, comp ) );
2632 }
2633 else if( cNodeName == wxT( "TRUNK" ) )
2634 {
2635 TRUNK trunk;
2636 trunk.Parse( cNode, aContext );
2637 Trunks.insert( std::make_pair( trunk.ID, trunk ) );
2638 }
2639 else if( cNodeName == wxT( "NET" ) )
2640 {
2641 NET_PCB net;
2642 net.Parse( cNode, aContext );
2643 Nets.insert( std::make_pair( net.ID, net ) );
2644 }
2645 else if( cNodeName == wxT( "TEMPLATE" ) )
2646 {
2647 TEMPLATE temp;
2648 temp.Parse( cNode, aContext );
2649 Templates.insert( std::make_pair( temp.ID, temp ) );
2650 }
2651 else if( cNodeName == wxT( "COPPER" ) )
2652 {
2653 COPPER copper;
2654 copper.Parse( cNode, aContext );
2655 Coppers.insert( std::make_pair( copper.ID, copper ) );
2656 }
2657 else if( cNodeName == wxT( "TEXT" ) )
2658 {
2659 TEXT txt;
2660 txt.Parse( cNode, aContext );
2661 Texts.insert( std::make_pair( txt.ID, txt ) );
2662 }
2663 else if( cNodeName == wxT( "DOCSYMBOL" ) )
2664 {
2665 DOCUMENTATION_SYMBOL docsym;
2666 docsym.Parse( cNode, aContext );
2667 DocumentationSymbols.insert( std::make_pair( docsym.ID, docsym ) );
2668 }
2669 else if( !dimensionsParsed && cNodeName == wxT( "DIMENSIONS" ) )
2670 {
2671 XNODE* dimensionNode = cNode->GetChildren();
2672
2673 for( ; dimensionNode; dimensionNode = dimensionNode->GetNext() )
2674 {
2675 if( DIMENSION::IsDimension( dimensionNode ) )
2676 {
2677 DIMENSION dim;
2678 dim.Parse( dimensionNode, aContext );
2679 Dimensions.insert( std::make_pair( dim.ID, dim ) );
2680 }
2681 else
2682 {
2683 WARN_UNKNOWN_NODE_IO_ERROR( dimensionNode->GetName(), cNodeName );
2684 }
2685 }
2686
2687 dimensionsParsed = true;
2688 }
2689 else if( cNodeName == wxT( "DRILLTABLE" ) )
2690 {
2691 DRILL_TABLE drilltable;
2692 drilltable.Parse( cNode, aContext );
2693 DrillTables.insert( std::make_pair( drilltable.ID, drilltable ) );
2694 }
2695 else if( cNodeName == wxT( "VHIERARCHY" ) )
2696 {
2697 VariantHierarchy.Parse( cNode, aContext );
2698 }
2699 else if( cNodeName == wxT( "ERRORMARK" ) )
2700 {
2701 //ignore (this is a DRC error marker in cadstar)
2702 continue;
2703 }
2704 else
2705 {
2706 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2707 }
2708
2709 aContext->CheckPointCallback();
2710 }
2711}
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