KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_writer_v10.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20// Schematic writer for the KiCad 10.0 file format, extracted from the 10.0.0 release. It can
21// only emit what that release knew, so its output always opens there.
22
24
25#include <algorithm>
26#include <fmt/format.h>
27#include <wx/mstream.h>
28#include <base_units.h>
29#include <bitmap_base.h>
30#include <build_version.h>
31#include <schematic_lexer.h>
32
33using namespace TSCHEMATIC_T;
36#include <schematic.h>
37#include <sch_bitmap.h>
38#include <sch_bus_entry.h>
39#include <sch_edit_frame.h> // SYMBOL_ORIENTATION_T
40#include <sch_group.h>
41#include <sch_junction.h>
42#include <sch_line.h>
43#include <sch_no_connect.h>
44#include <sch_pin.h>
45#include <sch_rule_area.h>
46#include <sch_screen.h>
47#include <sch_shape.h>
48#include <sch_sheet.h>
49#include <sch_sheet_pin.h>
50#include <sch_symbol.h>
51#include <sch_table.h>
52#include <sch_tablecell.h>
53#include <sch_text.h>
54#include <sch_textbox.h>
55#include <string_utils.h>
56#include <locale_io.h>
57#include <richio.h>
58
59
60// Era copies of the shared fill and shape helpers. The current ones emit newer tokens.
61static const char* emptyString = "";
62
63static void formatArc( OUTPUTFORMATTER* aFormatter, EDA_SHAPE* aArc, bool aIsPrivate, const STROKE_PARAMS& aStroke,
64 FILL_T aFillMode, const COLOR4D& aFillColor, bool aInvertY, const KIID& aUuid = niluuid );
65static void formatCircle( OUTPUTFORMATTER* aFormatter, EDA_SHAPE* aCircle, bool aIsPrivate,
66 const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor, bool aInvertY,
67 const KIID& aUuid = niluuid );
68static void formatRect( OUTPUTFORMATTER* aFormatter, EDA_SHAPE* aRect, bool aIsPrivate, const STROKE_PARAMS& aStroke,
69 FILL_T aFillMode, const COLOR4D& aFillColor, bool aInvertY, const KIID& aUuid = niluuid );
70static void formatBezier( OUTPUTFORMATTER* aFormatter, EDA_SHAPE* aBezier, bool aIsPrivate,
71 const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor, bool aInvertY,
72 const KIID& aUuid = niluuid );
73static void formatPoly( OUTPUTFORMATTER* aFormatter, EDA_SHAPE* aPolyLine, bool aIsPrivate,
74 const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor, bool aInvertY,
75 const KIID& aUuid = niluuid );
76
77static void formatFill( OUTPUTFORMATTER* aFormatter, FILL_T aFillMode, const COLOR4D& aFillColor )
78{
79 const char* fillType;
80
81 switch( aFillMode )
82 {
83 default:
84 case FILL_T::NO_FILL: fillType = "none"; break;
85 case FILL_T::FILLED_SHAPE: fillType = "outline"; break;
86 case FILL_T::FILLED_WITH_BG_BODYCOLOR: fillType = "background"; break;
87 case FILL_T::FILLED_WITH_COLOR: fillType = "color"; break;
88 case FILL_T::HATCH: fillType = "hatch"; break;
89 case FILL_T::REVERSE_HATCH: fillType = "reverse_hatch"; break;
90 case FILL_T::CROSS_HATCH: fillType = "cross_hatch"; break;
91 }
92
93 if( aFillMode == FILL_T::FILLED_WITH_COLOR || aFillMode == FILL_T::HATCH || aFillMode == FILL_T::REVERSE_HATCH
94 || aFillMode == FILL_T::CROSS_HATCH )
95 {
96 aFormatter->Print( "(fill (type %s) (color %d %d %d %s))", fillType, KiROUND( aFillColor.r * 255.0 ),
97 KiROUND( aFillColor.g * 255.0 ), KiROUND( aFillColor.b * 255.0 ),
98 FormatDouble2Str( aFillColor.a ).c_str() );
99 }
100 else
101 {
102 aFormatter->Print( "(fill (type %s))", fillType );
103 }
104}
105
106
108{
109 switch( aType )
110 {
111 case ELECTRICAL_PINTYPE::PT_INPUT: return SCHEMATIC_LEXER::TokenName( T_input );
112
113 case ELECTRICAL_PINTYPE::PT_OUTPUT: return SCHEMATIC_LEXER::TokenName( T_output );
114
115 case ELECTRICAL_PINTYPE::PT_BIDI: return SCHEMATIC_LEXER::TokenName( T_bidirectional );
116
117 case ELECTRICAL_PINTYPE::PT_TRISTATE: return SCHEMATIC_LEXER::TokenName( T_tri_state );
118
119 case ELECTRICAL_PINTYPE::PT_PASSIVE: return SCHEMATIC_LEXER::TokenName( T_passive );
120
121 case ELECTRICAL_PINTYPE::PT_NIC: return SCHEMATIC_LEXER::TokenName( T_free );
122
123 case ELECTRICAL_PINTYPE::PT_UNSPECIFIED: return SCHEMATIC_LEXER::TokenName( T_unspecified );
124
125 case ELECTRICAL_PINTYPE::PT_POWER_IN: return SCHEMATIC_LEXER::TokenName( T_power_in );
126
127 case ELECTRICAL_PINTYPE::PT_POWER_OUT: return SCHEMATIC_LEXER::TokenName( T_power_out );
128
129 case ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR: return SCHEMATIC_LEXER::TokenName( T_open_collector );
130
131 case ELECTRICAL_PINTYPE::PT_OPENEMITTER: return SCHEMATIC_LEXER::TokenName( T_open_emitter );
132
133 case ELECTRICAL_PINTYPE::PT_NC: return SCHEMATIC_LEXER::TokenName( T_no_connect );
134
135 default: wxFAIL_MSG( "Missing symbol library pin connection type" );
136 }
137
138 return emptyString;
139}
140
141
142static const char* getPinShapeToken( GRAPHIC_PINSHAPE aShape )
143{
144 switch( aShape )
145 {
146 case GRAPHIC_PINSHAPE::LINE: return SCHEMATIC_LEXER::TokenName( T_line );
147
148 case GRAPHIC_PINSHAPE::INVERTED: return SCHEMATIC_LEXER::TokenName( T_inverted );
149
150 case GRAPHIC_PINSHAPE::CLOCK: return SCHEMATIC_LEXER::TokenName( T_clock );
151
152 case GRAPHIC_PINSHAPE::INVERTED_CLOCK: return SCHEMATIC_LEXER::TokenName( T_inverted_clock );
153
154 case GRAPHIC_PINSHAPE::INPUT_LOW: return SCHEMATIC_LEXER::TokenName( T_input_low );
155
156 case GRAPHIC_PINSHAPE::CLOCK_LOW: return SCHEMATIC_LEXER::TokenName( T_clock_low );
157
158 case GRAPHIC_PINSHAPE::OUTPUT_LOW: return SCHEMATIC_LEXER::TokenName( T_output_low );
159
160 case GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK: return SCHEMATIC_LEXER::TokenName( T_edge_clock_high );
161
162 case GRAPHIC_PINSHAPE::NONLOGIC: return SCHEMATIC_LEXER::TokenName( T_non_logic );
163
164 default: wxFAIL_MSG( "Missing symbol library pin shape type" );
165 }
166
167 return emptyString;
168}
169
170
172{
173 switch( aOrientation )
174 {
179 default: wxFAIL_MSG( "Missing symbol library pin orientation type" ); return ANGLE_0;
180 }
181}
182
183
184static const char* getSheetPinShapeToken( LABEL_FLAG_SHAPE aShape )
185{
186 switch( aShape )
187 {
188 case LABEL_FLAG_SHAPE::L_INPUT: return SCHEMATIC_LEXER::TokenName( T_input );
189 case LABEL_FLAG_SHAPE::L_OUTPUT: return SCHEMATIC_LEXER::TokenName( T_output );
190 case LABEL_FLAG_SHAPE::L_BIDI: return SCHEMATIC_LEXER::TokenName( T_bidirectional );
191 case LABEL_FLAG_SHAPE::L_TRISTATE: return SCHEMATIC_LEXER::TokenName( T_tri_state );
192 case LABEL_FLAG_SHAPE::L_UNSPECIFIED: return SCHEMATIC_LEXER::TokenName( T_passive );
193 case LABEL_FLAG_SHAPE::F_DOT: return SCHEMATIC_LEXER::TokenName( T_dot );
194 case LABEL_FLAG_SHAPE::F_ROUND: return SCHEMATIC_LEXER::TokenName( T_round );
195 case LABEL_FLAG_SHAPE::F_DIAMOND: return SCHEMATIC_LEXER::TokenName( T_diamond );
196 case LABEL_FLAG_SHAPE::F_RECTANGLE: return SCHEMATIC_LEXER::TokenName( T_rectangle );
197 default: wxFAIL; return SCHEMATIC_LEXER::TokenName( T_passive );
198 }
199}
200
201
203{
204 switch( aSide )
205 {
207 case SHEET_SIDE::LEFT: return ANGLE_180;
208 case SHEET_SIDE::RIGHT: return ANGLE_0;
209 case SHEET_SIDE::TOP: return ANGLE_90;
210 case SHEET_SIDE::BOTTOM: return ANGLE_270;
211 default: wxFAIL; return ANGLE_0;
212 }
213}
214
215
216static const char* getTextTypeToken( KICAD_T aType )
217{
218 switch( aType )
219 {
220 case SCH_TEXT_T: return SCHEMATIC_LEXER::TokenName( T_text );
221 case SCH_LABEL_T: return SCHEMATIC_LEXER::TokenName( T_label );
222 case SCH_GLOBAL_LABEL_T: return SCHEMATIC_LEXER::TokenName( T_global_label );
223 case SCH_HIER_LABEL_T: return SCHEMATIC_LEXER::TokenName( T_hierarchical_label );
224 case SCH_DIRECTIVE_LABEL_T: return SCHEMATIC_LEXER::TokenName( T_netclass_flag );
225 default: wxFAIL; return SCHEMATIC_LEXER::TokenName( T_text );
226 }
227}
228
229
230static std::string formatIU( const int& aValue )
231{
233}
234
235
236static std::string formatIU( const VECTOR2I& aPt, bool aInvertY )
237{
238 VECTOR2I pt( aPt.x, aInvertY ? -aPt.y : aPt.y );
240}
241
242
243static void formatArc( OUTPUTFORMATTER* aFormatter, EDA_SHAPE* aArc, bool aIsPrivate, const STROKE_PARAMS& aStroke,
244 FILL_T aFillMode, const COLOR4D& aFillColor, bool aInvertY, const KIID& aUuid )
245{
246 aFormatter->Print( "(arc %s (start %s) (mid %s) (end %s)", aIsPrivate ? "private" : "",
247 formatIU( aArc->GetStart(), aInvertY ).c_str(), formatIU( aArc->GetArcMid(), aInvertY ).c_str(),
248 formatIU( aArc->GetEnd(), aInvertY ).c_str() );
249
250 KICAD_FORMAT::LEGACY::FormatStroke( aFormatter, aStroke, schIUScale );
251 formatFill( aFormatter, aFillMode, aFillColor );
252
253 if( aUuid != niluuid )
254 aFormatter->Print( "(uuid %s)", aFormatter->Quotew( aUuid.AsString() ).c_str() );
255
256 aFormatter->Print( ")" );
257}
258
259
260static void formatCircle( OUTPUTFORMATTER* aFormatter, EDA_SHAPE* aCircle, bool aIsPrivate,
261 const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor, bool aInvertY,
262 const KIID& aUuid )
263{
264 aFormatter->Print( "(circle %s (center %s) (radius %s)", aIsPrivate ? "private" : "",
265 formatIU( aCircle->GetStart(), aInvertY ).c_str(), formatIU( aCircle->GetRadius() ).c_str() );
266
267 KICAD_FORMAT::LEGACY::FormatStroke( aFormatter, aStroke, schIUScale );
268 formatFill( aFormatter, aFillMode, aFillColor );
269
270 if( aUuid != niluuid )
271 aFormatter->Print( "(uuid %s)", aFormatter->Quotew( aUuid.AsString() ).c_str() );
272
273 aFormatter->Print( ")" );
274}
275
276
277static void formatRect( OUTPUTFORMATTER* aFormatter, EDA_SHAPE* aRect, bool aIsPrivate, const STROKE_PARAMS& aStroke,
278 FILL_T aFillMode, const COLOR4D& aFillColor, bool aInvertY, const KIID& aUuid )
279{
280 aFormatter->Print( "(rectangle %s (start %s) (end %s)", aIsPrivate ? "private" : "",
281 formatIU( aRect->GetStart(), aInvertY ).c_str(), formatIU( aRect->GetEnd(), aInvertY ).c_str() );
282 if( aRect->GetCornerRadius() > 0 )
283 aFormatter->Print( "(radius %s)", formatIU( aRect->GetCornerRadius() ).c_str() );
284 KICAD_FORMAT::LEGACY::FormatStroke( aFormatter, aStroke, schIUScale );
285 formatFill( aFormatter, aFillMode, aFillColor );
286
287 if( aUuid != niluuid )
288 aFormatter->Print( "(uuid %s)", aFormatter->Quotew( aUuid.AsString() ).c_str() );
289
290 aFormatter->Print( ")" );
291}
292
293
294static void formatBezier( OUTPUTFORMATTER* aFormatter, EDA_SHAPE* aBezier, bool aIsPrivate,
295 const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor, bool aInvertY,
296 const KIID& aUuid )
297{
298 aFormatter->Print( "(bezier %s (pts ", aIsPrivate ? "private" : "" );
299
300 for( const VECTOR2I& pt :
301 { aBezier->GetStart(), aBezier->GetBezierC1(), aBezier->GetBezierC2(), aBezier->GetEnd() } )
302 {
303 aFormatter->Print( "(xy %s)", formatIU( pt, aInvertY ).c_str() );
304 }
305
306 aFormatter->Print( ")" ); // Closes pts token
307
308 KICAD_FORMAT::LEGACY::FormatStroke( aFormatter, aStroke, schIUScale );
309 formatFill( aFormatter, aFillMode, aFillColor );
310
311 if( aUuid != niluuid )
312 aFormatter->Print( "(uuid %s)", aFormatter->Quotew( aUuid.AsString() ).c_str() );
313
314 aFormatter->Print( ")" );
315}
316
317
318static void formatPoly( OUTPUTFORMATTER* aFormatter, EDA_SHAPE* aPolyLine, bool aIsPrivate,
319 const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor, bool aInvertY,
320 const KIID& aUuid )
321{
322 aFormatter->Print( "(polyline %s (pts ", aIsPrivate ? "private" : "" );
323
324 const SHAPE_POLY_SET& aPolySet = aPolyLine->GetPolyShape();
325
326 if( aPolySet.OutlineCount() == 0 )
327 {
328 // If we've managed to get a polyline with no points, that's probably a bad thing,
329 // but at least don't dereference it and crash.
330 wxFAIL_MSG( "Polyline has no outlines" );
331 }
332 else
333 {
334 const SHAPE_LINE_CHAIN& outline = aPolySet.Outline( 0 );
335
336 for( const VECTOR2I& pt : outline.CPoints() )
337 aFormatter->Print( "(xy %s)", formatIU( pt, aInvertY ).c_str() );
338
339 if( outline.IsClosed() && outline.PointCount() > 1 && outline.CPoint( -1 ) != outline.CPoint( 0 ) )
340 aFormatter->Print( "(xy %s)", formatIU( outline.CPoint( 0 ), aInvertY ).c_str() );
341 }
342
343 aFormatter->Print( ")" ); // Closes pts token
344
345 KICAD_FORMAT::LEGACY::FormatStroke( aFormatter, aStroke, schIUScale );
346 formatFill( aFormatter, aFillMode, aFillColor );
347
348 if( aUuid != niluuid )
349 aFormatter->Print( "(uuid %s)", aFormatter->Quotew( aUuid.AsString() ).c_str() );
350
351 aFormatter->Print( ")" );
352}
353
354
355static void libSaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMATTER& aFormatter, const wxString& aLibName = wxEmptyString,
356 bool aIncludeData = true );
357static void libSaveSymbolDrawItem( SCH_ITEM* aItem, OUTPUTFORMATTER& aFormatter );
358static void libSaveField( SCH_FIELD* aField, OUTPUTFORMATTER& aFormatter );
359static void libSavePin( SCH_PIN* aPin, OUTPUTFORMATTER& aFormatter );
360static void libSaveText( SCH_TEXT* aText, OUTPUTFORMATTER& aFormatter );
361static void libSaveTextBox( SCH_TEXTBOX* aTextBox, OUTPUTFORMATTER& aFormatter );
362static void libSaveDcmInfoAsFields( LIB_SYMBOL* aSymbol, OUTPUTFORMATTER& aFormatter );
363
364
365static void libSaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMATTER& aFormatter, const wxString& aLibName,
366 bool aIncludeData )
367{
368 wxCHECK_RET( aSymbol, "Invalid LIB_SYMBOL pointer." );
369
370 // If we've requested to embed the fonts in the symbol, do so.
371 // Otherwise, clear the embedded fonts from the symbol. Embedded
372 // fonts will be used if available
373 if( aSymbol->GetAreFontsEmbedded() )
374 aSymbol->EmbedFonts();
375 else
377
378 std::vector<SCH_FIELD*> orderedFields;
379 std::string name = aFormatter.Quotew( aSymbol->GetLibId().GetLibItemName().wx_str() );
380 std::string unitName = aSymbol->GetLibId().GetLibItemName();
381
382 if( !aLibName.IsEmpty() )
383 {
384 name = aFormatter.Quotew( aLibName );
385
386 LIB_ID unitId;
387
388 wxCHECK2( unitId.Parse( aLibName ) < 0, /* do nothing */ );
389
390 unitName = unitId.GetLibItemName();
391 }
392
393 if( aSymbol->IsRoot() )
394 {
395 aFormatter.Print( "(symbol %s", name.c_str() );
396
397 if( aSymbol->IsGlobalPower() )
398 aFormatter.Print( "(power global)" );
399 else if( aSymbol->IsLocalPower() )
400 aFormatter.Print( "(power local)" );
401
402 if( aSymbol->IsMultiBodyStyle() )
403 {
404 aFormatter.Print( "(body_styles " );
405
406 if( aSymbol->HasDeMorganBodyStyles() )
407 {
408 aFormatter.Print( "demorgan" );
409 }
410 else
411 {
412 for( const wxString& bodyStyle : aSymbol->GetBodyStyleNames() )
413 aFormatter.Print( "%s ", aFormatter.Quotew( bodyStyle ).c_str() );
414 }
415
416 aFormatter.Print( ")" );
417 }
418
419 if( !aSymbol->GetShowPinNumbers() )
420 aFormatter.Print( "(pin_numbers (hide yes))" );
421
422 if( aSymbol->GetPinNameOffset() != schIUScale.MilsToIU( DEFAULT_PIN_NAME_OFFSET )
423 || !aSymbol->GetShowPinNames() )
424 {
425 aFormatter.Print( "(pin_names" );
426
427 if( aSymbol->GetPinNameOffset() != schIUScale.MilsToIU( DEFAULT_PIN_NAME_OFFSET ) )
428 {
429 aFormatter.Print(
430 "(offset %s)",
432 }
433
434 if( !aSymbol->GetShowPinNames() )
435 KICAD_FORMAT::LEGACY::FormatBool( &aFormatter, "hide", true );
436
437 aFormatter.Print( ")" );
438 }
439
440 KICAD_FORMAT::LEGACY::FormatBool( &aFormatter, "exclude_from_sim", aSymbol->GetExcludedFromSim() );
441 KICAD_FORMAT::LEGACY::FormatBool( &aFormatter, "in_bom", !aSymbol->GetExcludedFromBOM() );
442 KICAD_FORMAT::LEGACY::FormatBool( &aFormatter, "on_board", !aSymbol->GetExcludedFromBoard() );
443 KICAD_FORMAT::LEGACY::FormatBool( &aFormatter, "in_pos_files", !aSymbol->GetExcludedFromPosFiles() );
444
445 KICAD_FORMAT::LEGACY::FormatBool( &aFormatter, "duplicate_pin_numbers_are_jumpers",
447
448 const JUMPER_GROUP_SET& jumperGroups = aSymbol->JumperPinGroups();
449
450 if( !jumperGroups.IsEmpty() )
451 {
452 aFormatter.Print( "(jumper_pin_groups" );
453
454 for( const JUMPER_GROUP& group : jumperGroups.GetAll() )
455 {
456 aFormatter.Print( "(" );
457
458 for( const wxString& padName : group.GetNames() )
459 aFormatter.Print( "%s ", aFormatter.Quotew( padName ).c_str() );
460
461 aFormatter.Print( ")" );
462 }
463
464 aFormatter.Print( ")" );
465 }
466
467 aSymbol->GetFields( orderedFields );
468
469 for( SCH_FIELD* field : orderedFields )
470 libSaveField( field, aFormatter );
471
472 // @todo At some point in the future the lock status (all units interchangeable) should
473 // be set deterministically. For now a custom lock property is used to preserve the
474 // locked flag state.
475 if( aSymbol->UnitsLocked() )
476 {
477 SCH_FIELD locked( nullptr, FIELD_T::USER, "ki_locked" );
478 libSaveField( &locked, aFormatter );
479 }
480
481 libSaveDcmInfoAsFields( aSymbol, aFormatter );
482
483 // Save the draw items grouped by units.
484 std::vector<LIB_SYMBOL_UNIT> units = aSymbol->GetUnitDrawItems();
485 std::sort( units.begin(), units.end(),
486 []( const LIB_SYMBOL_UNIT& a, const LIB_SYMBOL_UNIT& b )
487 {
488 if( a.m_unit == b.m_unit )
489 return a.m_bodyStyle < b.m_bodyStyle;
490
491 return a.m_unit < b.m_unit;
492 } );
493
494 for( const LIB_SYMBOL_UNIT& unit : units )
495 {
496 // Add quotes and escape chars like ") to the UTF8 unitName string
497 name = aFormatter.Quotes( unitName );
498 name.pop_back(); // Remove last char: the quote ending the string.
499
500 aFormatter.Print( "(symbol %s_%d_%d\"", name.c_str(), unit.m_unit, unit.m_bodyStyle );
501
502 // if the unit has a display name, write that
503 if( aSymbol->GetUnitDisplayNames().contains( unit.m_unit ) )
504 {
505 name = aSymbol->GetUnitDisplayNames().at( unit.m_unit );
506 aFormatter.Print( "(unit_name %s)", aFormatter.Quotes( name ).c_str() );
507 }
508
509 // Enforce item ordering
510 auto cmp = []( const SCH_ITEM* a, const SCH_ITEM* b )
511 {
512 return *a < *b;
513 };
514
515 std::multiset<SCH_ITEM*, decltype( cmp )> save_map( cmp );
516
517 for( SCH_ITEM* item : unit.m_items )
518 save_map.insert( item );
519
520 for( SCH_ITEM* item : save_map )
521 libSaveSymbolDrawItem( item, aFormatter );
522
523 aFormatter.Print( ")" );
524 }
525
526 KICAD_FORMAT::LEGACY::FormatBool( &aFormatter, "embedded_fonts", aSymbol->GetAreFontsEmbedded() );
527
528 if( !aSymbol->EmbeddedFileMap().empty() )
529 KICAD_FORMAT::LEGACY::FormatEmbeddedFilesV10( aFormatter, *aSymbol, aIncludeData );
530 }
531 else
532 {
533 std::shared_ptr<LIB_SYMBOL> parent = aSymbol->GetParent().lock();
534
535 wxASSERT( parent );
536
537 aFormatter.Print( "(symbol %s (extends %s)", name.c_str(), aFormatter.Quotew( parent->GetName() ).c_str() );
538
539 aSymbol->GetFields( orderedFields );
540
541 for( SCH_FIELD* field : orderedFields )
542 libSaveField( field, aFormatter );
543
544 libSaveDcmInfoAsFields( aSymbol, aFormatter );
545
546 KICAD_FORMAT::LEGACY::FormatBool( &aFormatter, "embedded_fonts", aSymbol->GetAreFontsEmbedded() );
547
548 if( !aSymbol->EmbeddedFileMap().empty() )
549 KICAD_FORMAT::LEGACY::FormatEmbeddedFilesV10( aFormatter, *aSymbol, aIncludeData );
550 }
551
552 aFormatter.Print( ")" );
553}
554
555
556static void libSaveDcmInfoAsFields( LIB_SYMBOL* aSymbol, OUTPUTFORMATTER& aFormatter )
557{
558 wxCHECK_RET( aSymbol, "Invalid LIB_SYMBOL pointer." );
559
560 if( !aSymbol->GetRawKeyWords().IsEmpty() )
561 {
562 SCH_FIELD keywords( nullptr, FIELD_T::USER, wxString( "ki_keywords" ) );
563 keywords.SetVisible( false );
564 keywords.SetText( aSymbol->GetRawKeyWords() );
565 libSaveField( &keywords, aFormatter );
566 }
567
568 wxArrayString fpFilters = aSymbol->GetFPFilters();
569
570 if( !fpFilters.IsEmpty() )
571 {
572 wxString tmp;
573
574 for( const wxString& filter : fpFilters )
575 {
576 // Spaces are not handled in fp filter names so escape spaces if any
577 wxString curr_filter = EscapeString( filter, ESCAPE_CONTEXT::CTX_NO_SPACE );
578
579 if( tmp.IsEmpty() )
580 tmp = curr_filter;
581 else
582 tmp += " " + curr_filter;
583 }
584
585 SCH_FIELD description( nullptr, FIELD_T::USER, wxString( "ki_fp_filters" ) );
586 description.SetVisible( false );
587 description.SetText( tmp );
588 libSaveField( &description, aFormatter );
589 }
590}
591
592
593static void libSaveSymbolDrawItem( SCH_ITEM* aItem, OUTPUTFORMATTER& aFormatter )
594{
595 wxCHECK_RET( aItem, "Invalid SCH_ITEM pointer." );
596
597 switch( aItem->Type() )
598 {
599 case SCH_SHAPE_T:
600 {
601 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
602 STROKE_PARAMS stroke = shape->GetStroke();
603 FILL_T fillMode = shape->GetFillMode();
604 COLOR4D fillColor = shape->GetFillColor();
605 bool isPrivate = shape->IsPrivate();
606
607 switch( shape->GetShape() )
608 {
609 case SHAPE_T::ARC: formatArc( &aFormatter, shape, isPrivate, stroke, fillMode, fillColor, true ); break;
610
611 case SHAPE_T::CIRCLE: formatCircle( &aFormatter, shape, isPrivate, stroke, fillMode, fillColor, true ); break;
612
613 case SHAPE_T::RECTANGLE: formatRect( &aFormatter, shape, isPrivate, stroke, fillMode, fillColor, true ); break;
614
615 case SHAPE_T::BEZIER: formatBezier( &aFormatter, shape, isPrivate, stroke, fillMode, fillColor, true ); break;
616
617 case SHAPE_T::POLY: formatPoly( &aFormatter, shape, isPrivate, stroke, fillMode, fillColor, true ); break;
618
619 default: UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
620 }
621
622 break;
623 }
624
625 case SCH_PIN_T: libSavePin( static_cast<SCH_PIN*>( aItem ), aFormatter ); break;
626
627 case SCH_TEXT_T: libSaveText( static_cast<SCH_TEXT*>( aItem ), aFormatter ); break;
628
629 case SCH_TEXTBOX_T: libSaveTextBox( static_cast<SCH_TEXTBOX*>( aItem ), aFormatter ); break;
630
631 default: UNIMPLEMENTED_FOR( aItem->GetClass() );
632 }
633}
634
635
636static void libSaveField( SCH_FIELD* aField, OUTPUTFORMATTER& aFormatter )
637{
638 wxCHECK_RET( aField && aField->Type() == SCH_FIELD_T, "Invalid SCH_FIELD object." );
639
640 wxString fieldName = aField->GetName();
641
642 if( aField->IsMandatory() )
643 fieldName = aField->GetUntranslatedName();
644
645 aFormatter.Print( "(property %s %s %s (at %s %s %s)", aField->IsPrivate() ? "private" : "",
646 aFormatter.Quotew( fieldName ).c_str(), aFormatter.Quotew( aField->GetText() ).c_str(),
649 fmt::format( "{:g}", aField->GetTextAngle().AsDegrees() ).c_str() );
650
651 KICAD_FORMAT::LEGACY::FormatBool( &aFormatter, "show_name", aField->IsNameShown() );
652
653 KICAD_FORMAT::LEGACY::FormatBool( &aFormatter, "do_not_autoplace", !aField->CanAutoplace() );
654
655 if( !aField->IsVisible() )
656 KICAD_FORMAT::LEGACY::FormatBool( &aFormatter, "hide", true );
657
658 KICAD_FORMAT::LEGACY::FormatTextV10( &aFormatter, *aField, schIUScale, 0 );
659 aFormatter.Print( ")" );
660}
661
662
663static void libSavePin( SCH_PIN* aPin, OUTPUTFORMATTER& aFormatter )
664{
665 wxCHECK_RET( aPin && aPin->Type() == SCH_PIN_T, "Invalid SCH_PIN object." );
666
667 aPin->ClearFlags( IS_CHANGED );
668
669 aFormatter.Print( "(pin %s %s (at %s %s %s) (length %s)", getPinElectricalTypeToken( aPin->GetType() ),
670 getPinShapeToken( aPin->GetShape() ),
675
676 if( !aPin->IsVisible() )
677 KICAD_FORMAT::LEGACY::FormatBool( &aFormatter, "hide", true );
678
679 // This follows the EDA_TEXT effects formatting for future expansion.
680 aFormatter.Print( "(name %s (effects (font (size %s %s))))", aFormatter.Quotew( aPin->GetName() ).c_str(),
683
684 aFormatter.Print( "(number %s (effects (font (size %s %s))))", aFormatter.Quotew( aPin->GetNumber() ).c_str(),
687
688
689 for( const std::pair<const wxString, SCH_PIN::ALT>& alt : aPin->GetAlternates() )
690 {
691 // There was a bug somewhere in the alternate pin code that allowed pin alternates with no
692 // name to be saved in library symbols. This strips any invalid alternates just in case
693 // that code resurfaces.
694 if( alt.second.m_Name.IsEmpty() )
695 continue;
696
697 aFormatter.Print( "(alternate %s %s %s)", aFormatter.Quotew( alt.second.m_Name ).c_str(),
698 getPinElectricalTypeToken( alt.second.m_Type ), getPinShapeToken( alt.second.m_Shape ) );
699 }
700
701 aFormatter.Print( ")" );
702}
703
704
705static void libSaveText( SCH_TEXT* aText, OUTPUTFORMATTER& aFormatter )
706{
707 wxCHECK_RET( aText && aText->Type() == SCH_TEXT_T, "Invalid SCH_TEXT object." );
708
709 aFormatter.Print( "(text %s %s (at %s %s %d)", aText->IsPrivate() ? "private" : "",
710 aFormatter.Quotew( aText->GetText() ).c_str(),
713 aText->GetTextAngle().AsTenthsOfADegree() );
714
715 KICAD_FORMAT::LEGACY::FormatTextV10( &aFormatter, *aText, schIUScale, 0 );
716 aFormatter.Print( ")" );
717}
718
719
720static void libSaveTextBox( SCH_TEXTBOX* aTextBox, OUTPUTFORMATTER& aFormatter )
721{
722 wxCHECK_RET( aTextBox && aTextBox->Type() == SCH_TEXTBOX_T, "Invalid SCH_TEXTBOX object." );
723
724 aFormatter.Print( "(text_box %s %s", aTextBox->IsPrivate() ? "private" : "",
725 aFormatter.Quotew( aTextBox->GetText() ).c_str() );
726
727 VECTOR2I pos = aTextBox->GetStart();
728 VECTOR2I size = aTextBox->GetEnd() - pos;
729
730 aFormatter.Print( "(at %s %s %s) (size %s %s) (margins %s %s %s %s)",
733 EDA_UNIT_UTILS::FormatAngle( aTextBox->GetTextAngle() ).c_str(),
740
741 KICAD_FORMAT::LEGACY::FormatStroke( &aFormatter, aTextBox->GetStroke(), schIUScale );
742 formatFill( &aFormatter, aTextBox->GetFillMode(), aTextBox->GetFillColor() );
743 KICAD_FORMAT::LEGACY::FormatTextV10( &aFormatter, *aTextBox, schIUScale, 0 );
744 aFormatter.Print( ")" );
745}
746
747
748void SCH_WRITER_V10::SaveSchematicFile( const wxString& aFileName, SCH_SHEET* aSheet, SCHEMATIC* aSchematic )
749{
750 LOCALE_IO toggle;
751
752 m_schematic = aSchematic;
753
754 PRETTIFIED_FILE_OUTPUTFORMATTER formatter( aFileName );
755
756 m_out = &formatter;
757 Format( aSheet );
758 formatter.Finish();
759 m_out = nullptr;
760}
761
762
763void SCH_WRITER_V10::SaveSymbolLibrary( const wxString& aFileName, const std::vector<LIB_SYMBOL*>& aSymbols )
764{
765 LOCALE_IO toggle;
766
767 PRETTIFIED_FILE_OUTPUTFORMATTER formatter( aFileName );
768
769 formatter.Print( "(kicad_symbol_lib (version %d) (generator \"kicad_symbol_editor\") "
770 "(generator_version \"%s\")",
772
773 for( LIB_SYMBOL* symbol : aSymbols )
774 libSaveSymbol( symbol, formatter, wxEmptyString );
775
776 formatter.Print( ")" );
777 formatter.Finish();
778}
779
780
782{
783 wxCHECK_RET( aSheet != nullptr, "NULL SCH_SHEET* object." );
784 wxCHECK_RET( m_schematic != nullptr, "NULL SCHEMATIC* object." );
785
786 SCH_SHEET_LIST sheets = m_schematic->Hierarchy();
787 SCH_SCREEN* screen = aSheet->GetScreen();
788
789 wxCHECK( screen, /* void */ );
790
791 // If we've requested to embed the fonts in the schematic, do so.
792 // Otherwise, clear the embedded fonts from the schematic. Embedded
793 // fonts will be used if available
794 if( m_schematic->GetAreFontsEmbedded() )
795 m_schematic->EmbedFonts();
796 else
797 m_schematic->GetEmbeddedFiles()->ClearEmbeddedFonts();
798
799 m_out->Print( "(kicad_sch (version %d) (generator \"eeschema\") (generator_version %s)",
801
803
806
807 // Save cache library.
808 m_out->Print( "(lib_symbols" );
809
810 for( const auto& [libItemName, libSymbol] : screen->GetLibSymbols() )
811 libSaveSymbol( libSymbol, *m_out, libItemName );
812
813 m_out->Print( ")" );
814
815 // Enforce item ordering
816 auto cmp = []( const SCH_ITEM* a, const SCH_ITEM* b )
817 {
818 if( a->Type() != b->Type() )
819 return a->Type() < b->Type();
820
821 return a->m_Uuid < b->m_Uuid;
822 };
823
824 std::multiset<SCH_ITEM*, decltype( cmp )> save_map( cmp );
825
826 for( SCH_ITEM* item : screen->Items() )
827 {
828 // Markers are not saved, so keep them from being considered below
829 if( item->Type() != SCH_MARKER_T )
830 save_map.insert( item );
831 }
832
833 for( SCH_ITEM* item : save_map )
834 {
835 switch( item->Type() )
836 {
837 case SCH_SYMBOL_T: saveSymbol( static_cast<SCH_SYMBOL*>( item ), *m_schematic, sheets, false ); break;
838
839 case SCH_BITMAP_T: saveBitmap( static_cast<SCH_BITMAP&>( *item ) ); break;
840
841 case SCH_SHEET_T: saveSheet( static_cast<SCH_SHEET*>( item ), sheets ); break;
842
843 case SCH_JUNCTION_T: saveJunction( static_cast<SCH_JUNCTION*>( item ) ); break;
844
845 case SCH_NO_CONNECT_T: saveNoConnect( static_cast<SCH_NO_CONNECT*>( item ) ); break;
846
848 case SCH_BUS_BUS_ENTRY_T: saveBusEntry( static_cast<SCH_BUS_ENTRY_BASE*>( item ) ); break;
849
850 case SCH_LINE_T: saveLine( static_cast<SCH_LINE*>( item ) ); break;
851
852 case SCH_SHAPE_T: saveShape( static_cast<SCH_SHAPE*>( item ) ); break;
853
854 case SCH_RULE_AREA_T: saveRuleArea( static_cast<SCH_RULE_AREA*>( item ) ); break;
855
856 case SCH_TEXT_T:
857 case SCH_LABEL_T:
859 case SCH_HIER_LABEL_T:
860 case SCH_DIRECTIVE_LABEL_T: saveText( static_cast<SCH_TEXT*>( item ) ); break;
861
862 case SCH_TEXTBOX_T: saveTextBox( static_cast<SCH_TEXTBOX*>( item ) ); break;
863
864 case SCH_TABLE_T: saveTable( static_cast<SCH_TABLE*>( item ) ); break;
865
866 case SCH_GROUP_T: saveGroup( static_cast<SCH_GROUP*>( item ) ); break;
867
868 default: wxASSERT( "Unexpected schematic object type in SCH_WRITER_V10::Format()" );
869 }
870 }
871
872 if( aSheet->HasRootInstance() )
873 {
874 std::vector<SCH_SHEET_INSTANCE> instances;
875
876 instances.emplace_back( aSheet->GetRootInstance() );
877 saveInstances( instances );
878 }
879
880 if( m_schematic->GetTopLevelSheet( 0 ) == aSheet )
881 {
882 KICAD_FORMAT::LEGACY::FormatBool( m_out, "embedded_fonts", m_schematic->GetAreFontsEmbedded() );
883
884 // Save any embedded files
885 if( !m_schematic->GetEmbeddedFiles()->IsEmpty() )
887 }
888
889 m_out->Print( ")" );
890}
891
892
893void SCH_WRITER_V10::saveSymbol( SCH_SYMBOL* aSymbol, const SCHEMATIC& aSchematic, const SCH_SHEET_LIST& aSheetList,
894 bool aForClipboard, const SCH_SHEET_PATH* aRelativePath )
895{
896 wxCHECK_RET( aSymbol != nullptr && m_out != nullptr, "" );
897
898 std::string libName;
899
900 wxString symbol_name = KICAD_FORMAT::LEGACY::FormatLibId( aSymbol->GetLibId() );
901
902 if( symbol_name.size() )
903 {
904 libName = toUTFTildaText( symbol_name );
905 }
906 else
907 {
908 libName = "_NONAME_";
909 }
910
911 EDA_ANGLE angle;
912 int orientation = aSymbol->GetOrientation() & ~( SYM_MIRROR_X | SYM_MIRROR_Y );
913
914 if( orientation == SYM_ORIENT_90 )
915 angle = ANGLE_90;
916 else if( orientation == SYM_ORIENT_180 )
917 angle = ANGLE_180;
918 else if( orientation == SYM_ORIENT_270 )
919 angle = ANGLE_270;
920 else
921 angle = ANGLE_0;
922
923 m_out->Print( "(symbol" );
924
925 if( !aSymbol->UseLibIdLookup() )
926 {
927 m_out->Print( "(lib_name %s)", m_out->Quotew( aSymbol->GetSchSymbolLibraryName() ).c_str() );
928 }
929
930 m_out->Print( "(lib_id %s) (at %s %s %s)",
931 m_out->Quotew( KICAD_FORMAT::LEGACY::FormatLibId( aSymbol->GetLibId() ).wx_str() ).c_str(),
934 EDA_UNIT_UTILS::FormatAngle( angle ).c_str() );
935
936 bool mirrorX = aSymbol->GetOrientation() & SYM_MIRROR_X;
937 bool mirrorY = aSymbol->GetOrientation() & SYM_MIRROR_Y;
938
939 if( mirrorX || mirrorY )
940 {
941 m_out->Print( "(mirror %s %s)", mirrorX ? "x" : "", mirrorY ? "y" : "" );
942 }
943
944 // The symbol unit is always set to the ordianal instance regardless of the current sheet
945 // instance to prevent file churn.
946 SCH_SYMBOL_INSTANCE ordinalInstance;
947
948 ordinalInstance.m_Reference = aSymbol->GetPrefix();
949
950 const SCH_SCREEN* parentScreen = static_cast<const SCH_SCREEN*>( aSymbol->GetParent() );
951
952 wxASSERT( parentScreen );
953
954 if( parentScreen && m_schematic )
955 {
956 std::optional<SCH_SHEET_PATH> ordinalPath = m_schematic->Hierarchy().GetOrdinalPath( parentScreen );
957
958 // Design blocks are saved from a temporary sheet & screen which will not be found in
959 // the schematic, and will therefore have no ordinal path.
960 // wxASSERT( ordinalPath );
961
962 if( ordinalPath )
963 aSymbol->GetInstance( ordinalInstance, ordinalPath->Path() );
964 else if( aSymbol->GetInstances().size() )
965 ordinalInstance = aSymbol->GetInstances()[0];
966 }
967
968 int unit = ordinalInstance.m_Unit;
969
970 if( aForClipboard && aRelativePath )
971 {
972 SCH_SYMBOL_INSTANCE unitInstance;
973
974 if( aSymbol->GetInstance( unitInstance, aRelativePath->Path() ) )
975 unit = unitInstance.m_Unit;
976 }
977
978 m_out->Print( "(unit %d)", unit );
979 m_out->Print( "(body_style %d)", aSymbol->GetBodyStyle() );
980
981 KICAD_FORMAT::LEGACY::FormatBool( m_out, "exclude_from_sim", aSymbol->GetExcludedFromSim() );
984 KICAD_FORMAT::LEGACY::FormatBool( m_out, "in_pos_files", !aSymbol->GetExcludedFromPosFiles() );
985 KICAD_FORMAT::LEGACY::FormatBool( m_out, "dnp", aSymbol->GetDNP() );
986
987 AUTOPLACE_ALGO fieldsAutoplaced = aSymbol->GetFieldsAutoplaced();
988
989 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
990 KICAD_FORMAT::LEGACY::FormatBool( m_out, "fields_autoplaced", true );
991
993
994 std::vector<SCH_FIELD*> orderedFields;
995 aSymbol->GetFields( orderedFields, false );
996
997 for( SCH_FIELD* field : orderedFields )
998 {
999 FIELD_T id = field->GetId();
1000 wxString value = field->GetText();
1001
1002 if( !aForClipboard && aSymbol->GetInstances().size() )
1003 {
1004 // The instance fields are always set to the default instance regardless of the
1005 // sheet instance to prevent file churn.
1006 if( id == FIELD_T::REFERENCE )
1007 field->SetText( ordinalInstance.m_Reference );
1008 }
1009 else if( aForClipboard && aSymbol->GetInstances().size() && aRelativePath && ( id == FIELD_T::REFERENCE ) )
1010 {
1011 SCH_SYMBOL_INSTANCE instance;
1012
1013 if( aSymbol->GetInstance( instance, aRelativePath->Path() ) )
1014 field->SetText( instance.m_Reference );
1015 }
1016
1017 try
1018 {
1019 saveField( field );
1020 }
1021 catch( ... )
1022 {
1023 // Restore the changed field text on write error.
1024 if( id == FIELD_T::REFERENCE )
1025 field->SetText( value );
1026
1027 throw;
1028 }
1029
1030 if( id == FIELD_T::REFERENCE )
1031 field->SetText( value );
1032 }
1033
1034 for( const std::unique_ptr<SCH_PIN>& pin : aSymbol->GetRawPins() )
1035 {
1036 // There was a bug introduced somewhere in the original alternated pin code that would
1037 // set the alternate pin to the default pin name which caused a number of library symbol
1038 // comparison issues. Clearing the alternate pin resolves this issue.
1039 if( pin->GetAlt().IsEmpty() || ( pin->GetAlt() == pin->GetBaseName() ) )
1040 {
1041 m_out->Print( "(pin %s", m_out->Quotew( pin->GetNumber() ).c_str() );
1043 m_out->Print( ")" );
1044 }
1045 else
1046 {
1047 m_out->Print( "(pin %s", m_out->Quotew( pin->GetNumber() ).c_str() );
1049 m_out->Print( "(alternate %s))", m_out->Quotew( pin->GetAlt() ).c_str() );
1050 }
1051 }
1052
1053 if( !aSymbol->GetInstances().empty() )
1054 {
1055 std::map<KIID, std::vector<SCH_SYMBOL_INSTANCE>> projectInstances;
1056 std::set<KIID> currentProjectKeys;
1057
1058 m_out->Print( "(instances" );
1059
1060 wxString projectName;
1061 KIID rootSheetUuid = aSchematic.Root().m_Uuid;
1062
1063 // Collect top-level sheet UUIDs to identify current project instances.
1064 // When root is virtual (niluuid), Path() skips it, so instance paths
1065 // start with the real top-level sheet UUID, not niluuid.
1066
1067 if( rootSheetUuid == niluuid )
1068 {
1069 for( const SCH_SHEET* sheet : aSchematic.GetTopLevelSheets() )
1070 currentProjectKeys.insert( sheet->m_Uuid );
1071 }
1072 else
1073 {
1074 currentProjectKeys.insert( rootSheetUuid );
1075 }
1076
1077 for( const SCH_SYMBOL_INSTANCE& inst : aSymbol->GetInstances() )
1078 {
1079 // Zero length KIID_PATH objects are not valid and will cause a crash below.
1080 wxCHECK2( inst.m_Path.size(), continue );
1081
1082 // If the instance data is part of this design but no longer has an associated sheet
1083 // path, don't save it. This prevents large amounts of orphaned instance data for the
1084 // current project from accumulating in the schematic files.
1085 //
1086 // The root sheet UUID can be niluuid for the virtual root. In that case, instance
1087 // paths may include the virtual root, but SCH_SHEET_PATH::Path() skips it. We need
1088 // to normalize the path by removing the virtual root before comparison.
1089 KIID_PATH pathToCheck = inst.m_Path;
1090
1091 // If root is virtual (niluuid) and path starts with virtual root, strip it
1092 if( rootSheetUuid == niluuid && !pathToCheck.empty() && pathToCheck[0] == niluuid )
1093 {
1094 if( pathToCheck.size() > 1 )
1095 {
1096 pathToCheck.erase( pathToCheck.begin() );
1097 }
1098 else
1099 {
1100 // Path only contains virtual root, skip it
1101 continue;
1102 }
1103 }
1104
1105 // Check if this instance is orphaned (no matching sheet path)
1106 // For virtual root, we check if the first real sheet matches one of the top-level sheets
1107 // For non-virtual root, we check if it matches the root sheet UUID
1108 bool belongsToThisProject = currentProjectKeys.count( pathToCheck[0] );
1109
1110 bool isOrphaned = belongsToThisProject && !aSheetList.GetSheetPathByKIIDPath( pathToCheck );
1111
1112 // Keep all instance data when copying to the clipboard. They may be needed on paste.
1113 if( !aForClipboard && isOrphaned )
1114 continue;
1115
1116 // Group by project - use the first real sheet KIID (after stripping virtual root)
1117 KIID projectKey = pathToCheck[0];
1118 auto it = projectInstances.find( projectKey );
1119
1120 if( it == projectInstances.end() )
1121 projectInstances[projectKey] = { inst };
1122 else
1123 it->second.emplace_back( inst );
1124 }
1125
1126 for( auto& [uuid, instances] : projectInstances )
1127 {
1128 wxCHECK2( instances.size(), continue );
1129
1130 // Sort project instances by KIID_PATH.
1131 std::sort( instances.begin(), instances.end(),
1132 []( SCH_SYMBOL_INSTANCE& aLhs, SCH_SYMBOL_INSTANCE& aRhs )
1133 {
1134 return aLhs.m_Path < aRhs.m_Path;
1135 } );
1136
1137 if( currentProjectKeys.count( uuid ) )
1138 projectName = m_schematic->Project().GetProjectName();
1139 else
1140 projectName = instances[0].m_ProjectName;
1141
1142 m_out->Print( "(project %s", m_out->Quotew( projectName ).c_str() );
1143
1144 for( const SCH_SYMBOL_INSTANCE& instance : instances )
1145 {
1146 wxString path;
1147 KIID_PATH tmp = instance.m_Path;
1148
1149 if( aForClipboard && aRelativePath )
1150 tmp.MakeRelativeTo( aRelativePath->Path() );
1151
1152 path = tmp.AsString();
1153
1154 m_out->Print( "(path %s (reference %s) (unit %d)", m_out->Quotew( path ).c_str(),
1155 m_out->Quotew( instance.m_Reference ).c_str(), instance.m_Unit );
1156
1157 if( !instance.m_Variants.empty() )
1158 {
1159 for( const auto& [name, variant] : instance.m_Variants )
1160 {
1161 m_out->Print( "(variant (name %s)", m_out->Quotew( name ).c_str() );
1162
1163 if( variant.m_DNP != aSymbol->GetDNP() )
1164 KICAD_FORMAT::LEGACY::FormatBool( m_out, "dnp", variant.m_DNP );
1165
1166 if( variant.m_ExcludedFromSim != aSymbol->GetExcludedFromSim() )
1167 KICAD_FORMAT::LEGACY::FormatBool( m_out, "exclude_from_sim", variant.m_ExcludedFromSim );
1168
1169 if( variant.m_ExcludedFromBOM != aSymbol->GetExcludedFromBOM() )
1170 KICAD_FORMAT::LEGACY::FormatBool( m_out, "in_bom", !variant.m_ExcludedFromBOM );
1171
1172 if( variant.m_ExcludedFromBoard != aSymbol->GetExcludedFromBoard() )
1173 KICAD_FORMAT::LEGACY::FormatBool( m_out, "on_board", !variant.m_ExcludedFromBoard );
1174
1175 if( variant.m_ExcludedFromPosFiles != aSymbol->GetExcludedFromPosFiles() )
1176 KICAD_FORMAT::LEGACY::FormatBool( m_out, "in_pos_files", !variant.m_ExcludedFromPosFiles );
1177
1178 for( const auto& [fname, fvalue] : variant.m_Fields )
1179 {
1180 m_out->Print( "(field (name %s) (value %s))", m_out->Quotew( fname ).c_str(),
1181 m_out->Quotew( fvalue ).c_str() );
1182 }
1183
1184 m_out->Print( ")" ); // Closes `variant` token.
1185 }
1186 }
1187
1188 m_out->Print( ")" ); // Closes `path` token.
1189 }
1190
1191 m_out->Print( ")" ); // Closes `project`.
1192 }
1193
1194 m_out->Print( ")" ); // Closes `instances`.
1195 }
1196
1197 m_out->Print( ")" ); // Closes `symbol`.
1198}
1199
1200
1202{
1203 wxCHECK_RET( aField != nullptr && m_out != nullptr, "" );
1204
1205 wxString fieldName;
1206
1207 if( aField->IsMandatory() )
1208 fieldName = aField->GetUntranslatedName();
1209 else
1210 fieldName = aField->GetName();
1211
1212 m_out->Print( "(property %s %s %s (at %s %s %s)", aField->IsPrivate() ? "private" : "",
1213 m_out->Quotew( fieldName ).c_str(), m_out->Quotew( aField->GetText() ).c_str(),
1216 EDA_UNIT_UTILS::FormatAngle( aField->GetTextAngle() ).c_str() );
1217
1218 if( !aField->IsVisible() )
1219 KICAD_FORMAT::LEGACY::FormatBool( m_out, "hide", true );
1220
1221 KICAD_FORMAT::LEGACY::FormatBool( m_out, "show_name", aField->IsNameShown() );
1222
1223 KICAD_FORMAT::LEGACY::FormatBool( m_out, "do_not_autoplace", !aField->CanAutoplace() );
1224
1226 || ( aField->GetTextHeight() != schIUScale.MilsToIU( DEFAULT_SIZE_TEXT ) ) )
1227 {
1229 }
1230
1231 m_out->Print( ")" ); // Closes `property` token
1232}
1233
1234
1236{
1237 wxCHECK_RET( m_out != nullptr, "" );
1238
1239 const REFERENCE_IMAGE& refImage = aBitmap.GetReferenceImage();
1240 const BITMAP_BASE& bitmapBase = refImage.GetImage();
1241
1242 const wxImage* image = bitmapBase.GetImageData();
1243
1244 wxCHECK_RET( image != nullptr, "wxImage* is NULL" );
1245
1246 m_out->Print( "(image (at %s %s)",
1249
1250 double scale = refImage.GetImageScale();
1251
1252 // 20230121 or older file format versions assumed 300 image PPI at load/save.
1253 // Let's keep compatibility by changing image scale.
1254 if( SCH_WRITER_V10::FORMAT_VERSION <= 20230121 )
1255 scale = scale * 300.0 / bitmapBase.GetPPI();
1256
1257 if( scale != 1.0 )
1258 m_out->Print( "%s", fmt::format( "(scale {:g})", refImage.GetImageScale() ).c_str() );
1259
1261
1262 wxMemoryOutputStream stream;
1263 bitmapBase.SaveImageData( stream );
1264
1265 KICAD_FORMAT::LEGACY::FormatStreamData( *m_out, *stream.GetOutputStreamBuffer() );
1266
1267 m_out->Print( ")" ); // Closes image token.
1268}
1269
1270
1271void SCH_WRITER_V10::saveSheet( SCH_SHEET* aSheet, const SCH_SHEET_LIST& aSheetList )
1272{
1273 wxCHECK_RET( aSheet != nullptr && m_out != nullptr, "" );
1274
1275 m_out->Print( "(sheet (at %s %s) (size %s %s)",
1280
1281 KICAD_FORMAT::LEGACY::FormatBool( m_out, "exclude_from_sim", aSheet->GetExcludedFromSim() );
1284 KICAD_FORMAT::LEGACY::FormatBool( m_out, "dnp", aSheet->GetDNP() );
1285
1286 AUTOPLACE_ALGO fieldsAutoplaced = aSheet->GetFieldsAutoplaced();
1287
1288 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
1289 KICAD_FORMAT::LEGACY::FormatBool( m_out, "fields_autoplaced", true );
1290
1291 STROKE_PARAMS stroke( aSheet->GetBorderWidth(), LINE_STYLE::SOLID, aSheet->GetBorderColor() );
1292
1293 stroke.SetWidth( aSheet->GetBorderWidth() );
1295
1296 m_out->Print( "(fill (color %d %d %d %s))", KiROUND( aSheet->GetBackgroundColor().r * 255.0 ),
1297 KiROUND( aSheet->GetBackgroundColor().g * 255.0 ), KiROUND( aSheet->GetBackgroundColor().b * 255.0 ),
1298 FormatDouble2Str( aSheet->GetBackgroundColor().a ).c_str() );
1299
1301
1302 for( SCH_FIELD& field : aSheet->GetFields() )
1303 saveField( &field );
1304
1305 for( const SCH_SHEET_PIN* pin : aSheet->GetPins() )
1306 {
1307 m_out->Print( "(pin %s %s (at %s %s %s)", EscapedUTF8( pin->GetText() ).c_str(),
1308 getSheetPinShapeToken( pin->GetShape() ),
1309 EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, pin->GetPosition().x ).c_str(),
1310 EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, pin->GetPosition().y ).c_str(),
1311 EDA_UNIT_UTILS::FormatAngle( getSheetPinAngle( pin->GetSide() ) ).c_str() );
1312
1314
1316
1317 m_out->Print( ")" ); // Closes pin token.
1318 }
1319
1320 // Save all sheet instances here except the root sheet instance.
1321 std::vector<SCH_SHEET_INSTANCE> sheetInstances = aSheet->GetInstances();
1322
1323 auto it = sheetInstances.begin();
1324
1325 while( it != sheetInstances.end() )
1326 {
1327 if( it->m_Path.size() == 0 )
1328 it = sheetInstances.erase( it );
1329 else
1330 it++;
1331 }
1332
1333 if( !sheetInstances.empty() )
1334 {
1335 m_out->Print( "(instances" );
1336
1337 KIID lastProjectUuid;
1338 KIID rootSheetUuid = m_schematic->Root().m_Uuid;
1339 bool inProjectClause = false;
1340
1341 std::set<KIID> currentProjectKeys;
1342
1343 if( rootSheetUuid == niluuid )
1344 {
1345 for( const SCH_SHEET* sheet : m_schematic->GetTopLevelSheets() )
1346 currentProjectKeys.insert( sheet->m_Uuid );
1347 }
1348 else
1349 {
1350 currentProjectKeys.insert( rootSheetUuid );
1351 }
1352
1353 for( size_t i = 0; i < sheetInstances.size(); i++ )
1354 {
1355 // If the instance data is part of this design but no longer has an associated sheet
1356 // path, don't save it. This prevents large amounts of orphaned instance data for the
1357 // current project from accumulating in the schematic files.
1358 //
1359 // Keep all instance data when copying to the clipboard. It may be needed on paste.
1360 bool belongsToThisProject =
1361 !sheetInstances[i].m_Path.empty() && currentProjectKeys.count( sheetInstances[i].m_Path[0] );
1362
1363 if( belongsToThisProject && !aSheetList.GetSheetPathByKIIDPath( sheetInstances[i].m_Path, false ) )
1364 {
1365 if( inProjectClause
1366 && ( ( i + 1 == sheetInstances.size() ) || lastProjectUuid != sheetInstances[i + 1].m_Path[0] ) )
1367 {
1368 m_out->Print( ")" ); // Closes `project` token.
1369 inProjectClause = false;
1370 }
1371
1372 continue;
1373 }
1374
1375 if( lastProjectUuid != sheetInstances[i].m_Path[0] )
1376 {
1377 wxString projectName;
1378
1379 if( belongsToThisProject )
1380 projectName = m_schematic->Project().GetProjectName();
1381 else
1382 projectName = sheetInstances[i].m_ProjectName;
1383
1384 lastProjectUuid = sheetInstances[i].m_Path[0];
1385 m_out->Print( "(project %s", m_out->Quotew( projectName ).c_str() );
1386 inProjectClause = true;
1387 }
1388
1389 wxString path = sheetInstances[i].m_Path.AsString();
1390
1391 m_out->Print( "(path %s (page %s)", m_out->Quotew( path ).c_str(),
1392 m_out->Quotew( sheetInstances[i].m_PageNumber ).c_str() );
1393
1394 if( !sheetInstances[i].m_Variants.empty() )
1395 {
1396 for( const auto& [name, variant] : sheetInstances[i].m_Variants )
1397 {
1398 m_out->Print( "(variant (name %s)", m_out->Quotew( name ).c_str() );
1399
1400 if( variant.m_DNP != aSheet->GetDNP() )
1401 KICAD_FORMAT::LEGACY::FormatBool( m_out, "dnp", variant.m_DNP );
1402
1403 if( variant.m_ExcludedFromSim != aSheet->GetExcludedFromSim() )
1404 KICAD_FORMAT::LEGACY::FormatBool( m_out, "exclude_from_sim", variant.m_ExcludedFromSim );
1405
1406 if( variant.m_ExcludedFromBOM != aSheet->GetExcludedFromBOM() )
1407 KICAD_FORMAT::LEGACY::FormatBool( m_out, "in_bom", !variant.m_ExcludedFromBOM );
1408
1409 for( const auto& [fname, fvalue] : variant.m_Fields )
1410 {
1411 m_out->Print( "(field (name %s) (value %s))", m_out->Quotew( fname ).c_str(),
1412 m_out->Quotew( fvalue ).c_str() );
1413 }
1414
1415 m_out->Print( ")" ); // Closes `variant` token.
1416 }
1417 }
1418
1419 m_out->Print( ")" ); // Closes `path` token.
1420
1421 if( inProjectClause
1422 && ( ( i + 1 == sheetInstances.size() ) || lastProjectUuid != sheetInstances[i + 1].m_Path[0] ) )
1423 {
1424 m_out->Print( ")" ); // Closes `project` token.
1425 inProjectClause = false;
1426 }
1427 }
1428
1429 m_out->Print( ")" ); // Closes `instances` token.
1430 }
1431
1432 m_out->Print( ")" ); // Closes sheet token.
1433}
1434
1435
1437{
1438 wxCHECK_RET( aJunction != nullptr && m_out != nullptr, "" );
1439
1440 m_out->Print( "(junction (at %s %s) (diameter %s) (color %d %d %d %s)",
1444 KiROUND( aJunction->GetColor().r * 255.0 ), KiROUND( aJunction->GetColor().g * 255.0 ),
1445 KiROUND( aJunction->GetColor().b * 255.0 ), FormatDouble2Str( aJunction->GetColor().a ).c_str() );
1446
1448 m_out->Print( ")" );
1449}
1450
1451
1453{
1454 wxCHECK_RET( aNoConnect != nullptr && m_out != nullptr, "" );
1455
1456 m_out->Print( "(no_connect (at %s %s)",
1458 EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aNoConnect->GetPosition().y ).c_str() );
1459
1461 m_out->Print( ")" );
1462}
1463
1464
1466{
1467 wxCHECK_RET( aBusEntry != nullptr && m_out != nullptr, "" );
1468
1469 // Bus to bus entries are converted to bus line segments.
1470 if( aBusEntry->GetClass() == "SCH_BUS_BUS_ENTRY" )
1471 {
1472 SCH_LINE busEntryLine( aBusEntry->GetPosition(), LAYER_BUS );
1473
1474 busEntryLine.SetEndPoint( aBusEntry->GetEnd() );
1475 saveLine( &busEntryLine );
1476 return;
1477 }
1478
1479 m_out->Print( "(bus_entry (at %s %s) (size %s %s)",
1483 EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aBusEntry->GetSize().y ).c_str() );
1484
1487 m_out->Print( ")" );
1488}
1489
1490
1492{
1493 wxCHECK_RET( aShape != nullptr && m_out != nullptr, "" );
1494
1495 switch( aShape->GetShape() )
1496 {
1497 case SHAPE_T::ARC:
1498 formatArc( m_out, aShape, false, aShape->GetStroke(), aShape->GetFillMode(), aShape->GetFillColor(), false,
1499 aShape->m_Uuid );
1500 break;
1501
1502 case SHAPE_T::CIRCLE:
1503 formatCircle( m_out, aShape, false, aShape->GetStroke(), aShape->GetFillMode(), aShape->GetFillColor(), false,
1504 aShape->m_Uuid );
1505 break;
1506
1507 case SHAPE_T::RECTANGLE:
1508 formatRect( m_out, aShape, false, aShape->GetStroke(), aShape->GetFillMode(), aShape->GetFillColor(), false,
1509 aShape->m_Uuid );
1510 break;
1511
1512 case SHAPE_T::BEZIER:
1513 formatBezier( m_out, aShape, false, aShape->GetStroke(), aShape->GetFillMode(), aShape->GetFillColor(), false,
1514 aShape->m_Uuid );
1515 break;
1516
1517 case SHAPE_T::POLY:
1518 formatPoly( m_out, aShape, false, aShape->GetStroke(), aShape->GetFillMode(), aShape->GetFillColor(), false,
1519 aShape->m_Uuid );
1520 break;
1521
1522 default: UNIMPLEMENTED_FOR( aShape->SHAPE_T_asString() );
1523 }
1524}
1525
1526
1528{
1529 wxCHECK_RET( aRuleArea != nullptr && m_out != nullptr, "" );
1530
1531 m_out->Print( "(rule_area " );
1532
1533 KICAD_FORMAT::LEGACY::FormatBool( m_out, "exclude_from_sim", aRuleArea->GetExcludedFromSim() );
1534 KICAD_FORMAT::LEGACY::FormatBool( m_out, "in_bom", !aRuleArea->GetExcludedFromBOM() );
1535 KICAD_FORMAT::LEGACY::FormatBool( m_out, "on_board", !aRuleArea->GetExcludedFromBoard() );
1536 KICAD_FORMAT::LEGACY::FormatBool( m_out, "dnp", aRuleArea->GetDNP() );
1537
1538 saveShape( aRuleArea );
1539
1540 m_out->Print( ")" );
1541}
1542
1543
1545{
1546 wxCHECK_RET( aLine != nullptr && m_out != nullptr, "" );
1547
1548 wxString lineType;
1549
1550 STROKE_PARAMS line_stroke = aLine->GetStroke();
1551
1552 switch( aLine->GetLayer() )
1553 {
1554 case LAYER_BUS: lineType = "bus"; break;
1555 case LAYER_WIRE: lineType = "wire"; break;
1556 case LAYER_NOTES: lineType = "polyline"; break;
1557 default: UNIMPLEMENTED_FOR( LayerName( aLine->GetLayer() ) );
1558 }
1559
1560 m_out->Print( "(%s (pts (xy %s %s) (xy %s %s))", TO_UTF8( lineType ),
1565
1568 m_out->Print( ")" );
1569}
1570
1571
1573{
1574 wxCHECK_RET( aText != nullptr && m_out != nullptr, "" );
1575
1576 // Note: label is nullptr SCH_TEXT, but not for SCH_LABEL_XXX,
1577 SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( aText );
1578
1579 m_out->Print( "(%s %s", getTextTypeToken( aText->Type() ), m_out->Quotew( aText->GetText() ).c_str() );
1580
1581 if( aText->Type() == SCH_TEXT_T )
1582 KICAD_FORMAT::LEGACY::FormatBool( m_out, "exclude_from_sim", aText->GetExcludedFromSim() );
1583
1584 if( aText->Type() == SCH_DIRECTIVE_LABEL_T )
1585 {
1586 SCH_DIRECTIVE_LABEL* flag = static_cast<SCH_DIRECTIVE_LABEL*>( aText );
1587
1588 m_out->Print( "(length %s)", EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, flag->GetPinLength() ).c_str() );
1589 }
1590
1591 EDA_ANGLE angle = aText->GetTextAngle();
1592
1593 if( label )
1594 {
1595 if( label->Type() == SCH_GLOBAL_LABEL_T || label->Type() == SCH_HIER_LABEL_T
1596 || label->Type() == SCH_DIRECTIVE_LABEL_T )
1597 {
1598 m_out->Print( "(shape %s)", getSheetPinShapeToken( label->GetShape() ) );
1599 }
1600
1601 // The angle of the text is always 0 or 90 degrees for readibility reasons,
1602 // but the item itself can have more rotation (-90 and 180 deg)
1603 switch( label->GetSpinStyle() )
1604 {
1605 default:
1606 case SPIN_STYLE::LEFT: angle += ANGLE_180; break;
1607 case SPIN_STYLE::UP: break;
1608 case SPIN_STYLE::RIGHT: break;
1609 case SPIN_STYLE::BOTTOM: angle += ANGLE_180; break;
1610 }
1611 }
1612
1613 m_out->Print( "(at %s %s %s)", EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aText->GetPosition().x ).c_str(),
1615 EDA_UNIT_UTILS::FormatAngle( angle ).c_str() );
1616
1617 if( label && !label->GetFields().empty() )
1618 {
1619 AUTOPLACE_ALGO fieldsAutoplaced = label->GetFieldsAutoplaced();
1620
1621 if( fieldsAutoplaced == AUTOPLACE_AUTO || fieldsAutoplaced == AUTOPLACE_MANUAL )
1622 KICAD_FORMAT::LEGACY::FormatBool( m_out, "fields_autoplaced", true );
1623 }
1624
1627
1628 if( label )
1629 {
1630 for( SCH_FIELD& field : label->GetFields() )
1631 saveField( &field );
1632 }
1633
1634 m_out->Print( ")" ); // Closes text token.
1635}
1636
1637
1639{
1640 wxCHECK_RET( aTextBox != nullptr && m_out != nullptr, "" );
1641
1642 m_out->Print( "(%s %s", aTextBox->Type() == SCH_TABLECELL_T ? "table_cell" : "text_box",
1643 m_out->Quotew( aTextBox->GetText() ).c_str() );
1644
1645 KICAD_FORMAT::LEGACY::FormatBool( m_out, "exclude_from_sim", aTextBox->GetExcludedFromSim() );
1646
1647 VECTOR2I pos = aTextBox->GetStart();
1648 VECTOR2I size = aTextBox->GetEnd() - pos;
1649
1650 m_out->Print( "(at %s %s %s) (size %s %s) (margins %s %s %s %s)",
1653 EDA_UNIT_UTILS::FormatAngle( aTextBox->GetTextAngle() ).c_str(),
1660
1661 if( SCH_TABLECELL* cell = dynamic_cast<SCH_TABLECELL*>( aTextBox ) )
1662 m_out->Print( "(span %d %d)", cell->GetColSpan(), cell->GetRowSpan() );
1663
1664 if( aTextBox->Type() != SCH_TABLECELL_T )
1666
1667 formatFill( m_out, aTextBox->GetFillMode(), aTextBox->GetFillColor() );
1670 m_out->Print( ")" );
1671}
1672
1673
1675{
1676 if( aTable->GetFlags() & SKIP_STRUCT )
1677 {
1678 aTable = static_cast<SCH_TABLE*>( aTable->Clone() );
1679
1680 int minCol = aTable->GetColCount();
1681 int maxCol = -1;
1682 int minRow = aTable->GetRowCount();
1683 int maxRow = -1;
1684
1685 for( int row = 0; row < aTable->GetRowCount(); ++row )
1686 {
1687 for( int col = 0; col < aTable->GetColCount(); ++col )
1688 {
1689 SCH_TABLECELL* cell = aTable->GetCell( row, col );
1690
1691 if( cell->IsSelected() )
1692 {
1693 minRow = std::min( minRow, row );
1694 maxRow = std::max( maxRow, row );
1695 minCol = std::min( minCol, col );
1696 maxCol = std::max( maxCol, col );
1697 }
1698 else
1699 {
1700 cell->SetFlags( STRUCT_DELETED );
1701 }
1702 }
1703 }
1704
1705 wxCHECK_MSG( maxCol >= minCol && maxRow >= minRow, /*void*/, wxT( "No selected cells!" ) );
1706
1707 int destRow = 0;
1708
1709 for( int row = minRow; row <= maxRow; row++ )
1710 aTable->SetRowHeight( destRow++, aTable->GetRowHeight( row ) );
1711
1712 int destCol = 0;
1713
1714 for( int col = minCol; col <= maxCol; col++ )
1715 aTable->SetColWidth( destCol++, aTable->GetColWidth( col ) );
1716
1717 aTable->DeleteMarkedCells();
1718 aTable->SetColCount( ( maxCol - minCol ) + 1 );
1719 }
1720
1721 wxCHECK_RET( aTable != nullptr && m_out != nullptr, "" );
1722
1723 m_out->Print( "(table (column_count %d)", aTable->GetColCount() );
1724
1725 m_out->Print( "(border" );
1726 KICAD_FORMAT::LEGACY::FormatBool( m_out, "external", aTable->StrokeExternal() );
1728
1729 if( aTable->StrokeExternal() || aTable->StrokeHeaderSeparator() )
1731
1732 m_out->Print( ")" ); // Close `border` token.
1733
1734 m_out->Print( "(separators" );
1737
1738 if( aTable->StrokeRows() || aTable->StrokeColumns() )
1740
1741 m_out->Print( ")" ); // Close `separators` token.
1742
1743 m_out->Print( "(column_widths" );
1744
1745 for( int col = 0; col < aTable->GetColCount(); ++col )
1746 {
1747 m_out->Print( " %s", EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aTable->GetColWidth( col ) ).c_str() );
1748 }
1749
1750 m_out->Print( ")" );
1751
1752 m_out->Print( "(row_heights" );
1753
1754 for( int row = 0; row < aTable->GetRowCount(); ++row )
1755 {
1756 m_out->Print( " %s", EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aTable->GetRowHeight( row ) ).c_str() );
1757 }
1758
1759 m_out->Print( ")" );
1760
1762
1763 m_out->Print( "(cells" );
1764
1765 for( SCH_TABLECELL* cell : aTable->GetCells() )
1766 saveTextBox( cell );
1767
1768 m_out->Print( ")" ); // Close `cells` token.
1769 m_out->Print( ")" ); // Close `table` token.
1770
1771 if( aTable->GetFlags() & SKIP_STRUCT )
1772 delete aTable;
1773}
1774
1775
1777{
1778 // Don't write empty groups
1779 if( aGroup->GetItems().empty() )
1780 return;
1781
1782 m_out->Print( "(group %s", m_out->Quotew( aGroup->GetName() ).c_str() );
1783
1785
1786 if( aGroup->IsLocked() )
1787 KICAD_FORMAT::LEGACY::FormatBool( m_out, "locked", true );
1788
1789 if( aGroup->HasDesignBlockLink() )
1790 m_out->Print( "(lib_id \"%s\")", KICAD_FORMAT::LEGACY::FormatLibId( aGroup->GetDesignBlockLibId() ).c_str() );
1791
1792 wxArrayString memberIds;
1793
1794 for( EDA_ITEM* member : aGroup->GetItems() )
1795 memberIds.Add( member->m_Uuid.AsString() );
1796
1797 memberIds.Sort();
1798
1799 m_out->Print( "(members" );
1800
1801 for( const wxString& memberId : memberIds )
1802 m_out->Print( " %s", m_out->Quotew( memberId ).c_str() );
1803
1804 m_out->Print( ")" ); // Close `members` token.
1805 m_out->Print( ")" ); // Close `group` token.
1806}
1807
1808
1809void SCH_WRITER_V10::saveInstances( const std::vector<SCH_SHEET_INSTANCE>& aInstances )
1810{
1811 if( aInstances.size() )
1812 {
1813 m_out->Print( "(sheet_instances" );
1814
1815 for( const SCH_SHEET_INSTANCE& instance : aInstances )
1816 {
1817 wxString path = instance.m_Path.AsString();
1818
1819 if( path.IsEmpty() )
1820 path = wxT( "/" ); // Root path
1821
1822 m_out->Print( "(path %s (page %s))", m_out->Quotew( path ).c_str(),
1823 m_out->Quotew( instance.m_PageNumber ).c_str() );
1824 }
1825
1826 m_out->Print( ")" ); // Close sheet instances token.
1827 }
1828}
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:130
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
wxString GetMajorMinorVersion()
Get only the major and minor version in a string major.minor.
This class handle bitmap images in KiCad.
Definition bitmap_base.h:45
bool SaveImageData(wxOutputStream &aOutStream) const
Write the bitmap data to aOutStream.
int GetPPI() const
wxImage * GetImageData()
Definition bitmap_base.h:64
int AsTenthsOfADegree() const
Definition eda_angle.h:117
double AsDegrees() const
Definition eda_angle.h:115
const LIB_ID & GetDesignBlockLibId() const
Definition eda_group.h:102
std::unordered_set< EDA_ITEM * > & GetItems()
Definition eda_group.h:78
wxString GetName() const
Definition eda_group.h:75
bool HasDesignBlockLink() const
Definition eda_group.h:99
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:158
const KIID m_Uuid
Definition eda_item.h:599
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:160
bool IsSelected() const
Definition eda_item.h:134
EDA_ITEM * GetParent() const
Definition eda_item.h:112
EDA_ITEM_FLAGS GetFlags() const
Definition eda_item.h:167
const VECTOR2I & GetBezierC2() const
Definition eda_shape.h:368
FILL_T GetFillMode() const
Definition eda_shape.h:148
SHAPE_POLY_SET & GetPolyShape()
int GetRadius() const
SHAPE_T GetShape() const
Definition eda_shape.h:175
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:325
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:275
COLOR4D GetFillColor() const
Definition eda_shape.h:159
wxString SHAPE_T_asString() const
const VECTOR2I & GetBezierC1() const
Definition eda_shape.h:365
int GetCornerRadius() const
VECTOR2I GetArcMid() const
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:118
virtual bool IsVisible() const
Definition eda_text.h:226
virtual int GetTextHeight() const
Definition eda_text.h:307
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:347
virtual EDA_ANGLE GetTextAngle() const
Definition eda_text.h:178
void ClearEmbeddedFonts()
Remove all embedded fonts from the collection.
const std::map< wxString, std::shared_ptr< EMBEDDED_FILE > > & EmbeddedFileMap() const
Provide an iterable view of the file collection.
bool GetAreFontsEmbedded() const
Represents an (ordered) list of JUMPER_GROUP objects.
const std::vector< JUMPER_GROUP > & GetAll() const
bool IsEmpty() const
Represents a group of jumper pins or pads, keyed by name.
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
double r
Red component.
Definition color4d.h:391
double g
Green component.
Definition color4d.h:392
double a
Alpha component.
Definition color4d.h:394
double b
Blue component.
Definition color4d.h:393
bool MakeRelativeTo(const KIID_PATH &aPath)
Definition kiid.cpp:378
wxString AsString() const
Definition kiid.cpp:423
Definition kiid.h:46
wxString AsString() const
Definition kiid.cpp:264
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition lib_id.cpp:65
const UTF8 & GetLibItemName() const
Definition lib_id.h:98
Define a library symbol object.
Definition lib_symbol.h:114
const wxString & GetRawKeyWords() const
Return only this symbol's keywords, without inheriting from its parent.
Definition lib_symbol.h:218
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:190
std::weak_ptr< LIB_SYMBOL > & GetParent()
Definition lib_symbol.h:152
void GetFields(std::vector< SCH_FIELD * > &aList, bool aVisibleOnly=false) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
bool UnitsLocked() const
Check whether symbol units are interchangeable.
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
Definition lib_symbol.h:240
std::vector< struct LIB_SYMBOL_UNIT > GetUnitDrawItems()
Return a list of SCH_ITEM objects separated by unit and convert number.
std::map< int, wxString > & GetUnitDisplayNames()
Definition lib_symbol.h:881
bool IsMultiBodyStyle() const override
Definition lib_symbol.h:902
JUMPER_GROUP_SET & JumperPinGroups()
Each jumper pin group is a set of pin numbers that should be treated as internally connected.
Definition lib_symbol.h:891
bool IsLocalPower() const override
wxArrayString GetFPFilters() const
Definition lib_symbol.h:252
const std::vector< wxString > & GetBodyStyleNames() const
bool HasDeMorganBodyStyles() const override
EMBEDDED_FILES * GetEmbeddedFiles() override
bool IsGlobalPower() const override
bool GetDuplicatePinNumbersAreJumpers() const
Definition lib_symbol.h:884
void EmbedFonts() override
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
An interface used to output 8 bit text in a convenient way.
Definition richio.h:294
std::string Quotew(const wxString &aWrapee) const
Definition richio.cpp:505
int PRINTF_FUNC_N Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition richio.cpp:432
virtual std::string Quotes(const std::string &aWrapee) const
Check aWrapee input string for a need to be quoted (e.g.
Definition richio.cpp:466
bool Finish() override
Runs prettification over the buffered bytes, writes them to the sibling temp file,...
Definition richio.cpp:710
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
VECTOR2I GetPosition() const
const BITMAP_BASE & GetImage() const
Get the underlying image.
double GetImageScale() const
Holds all the data relating to one schematic.
Definition schematic.h:149
SCH_SHEET & Root() const
Definition schematic.h:200
std::vector< SCH_SHEET * > GetTopLevelSheets() const
Get the list of top-level sheets.
Object to handle a bitmap image that can be inserted in a schematic.
Definition sch_bitmap.h:36
REFERENCE_IMAGE & GetReferenceImage()
Definition sch_bitmap.h:50
Base class for a bus or wire entry.
VECTOR2I GetSize() const
VECTOR2I GetPosition() const override
virtual STROKE_PARAMS GetStroke() const override
VECTOR2I GetEnd() const
bool IsMandatory() const
VECTOR2I GetPosition() const override
bool IsNameShown() const
Definition sch_field.h:229
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:139
wxString GetUntranslatedName() const
Get the untranslated field name for storage, variable look-up, etc.
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
bool CanAutoplace() const
Definition sch_field.h:240
void SetText(const wxString &aText) override
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:48
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
int GetBodyStyle() const
Definition sch_item.h:253
bool IsLocked() const override
Definition sch_item.cpp:179
bool IsPrivate() const
Definition sch_item.h:259
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition sch_item.h:353
AUTOPLACE_ALGO GetFieldsAutoplaced() const
Return whether the fields have been automatically placed.
Definition sch_item.h:673
wxString GetClass() const override
Return the class name.
Definition sch_item.h:180
int GetDiameter() const
VECTOR2I GetPosition() const override
KIGFX::COLOR4D GetColor() const
SPIN_STYLE GetSpinStyle() const
LABEL_FLAG_SHAPE GetShape() const
Definition sch_label.h:178
std::vector< SCH_FIELD > & GetFields()
Definition sch_label.h:210
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:39
virtual STROKE_PARAMS GetStroke() const override
Definition sch_line.h:198
VECTOR2I GetEndPoint() const
Definition sch_line.h:145
VECTOR2I GetStartPoint() const
Definition sch_line.h:136
void SetEndPoint(const VECTOR2I &aPosition)
Definition sch_line.h:146
VECTOR2I GetPosition() const override
int GetNumberTextSize() const
Definition sch_pin.cpp:882
int GetLength() const
Definition sch_pin.cpp:421
const std::map< wxString, ALT > & GetAlternates() const
Definition sch_pin.h:219
bool IsVisible() const
Definition sch_pin.cpp:513
const wxString & GetName() const
Definition sch_pin.cpp:527
PIN_ORIENTATION GetOrientation() const
Definition sch_pin.cpp:386
VECTOR2I GetPosition() const override
Definition sch_pin.cpp:378
int GetNameTextSize() const
Definition sch_pin.cpp:856
const wxString & GetNumber() const
Definition sch_pin.h:144
GRAPHIC_PINSHAPE GetShape() const
Definition sch_pin.cpp:400
ELECTRICAL_PINTYPE GetType() const
Definition sch_pin.cpp:435
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flag.
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
const PAGE_INFO & GetPageSettings() const
Definition sch_screen.h:144
const std::map< wxString, LIB_SYMBOL * > & GetLibSymbols() const
Fetch a list of unique LIB_SYMBOL object pointers required to properly render each SCH_SYMBOL in this...
Definition sch_screen.h:557
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:122
const KIID & GetUuid() const
Definition sch_screen.h:594
TITLE_BLOCK & GetTitleBlock()
Definition sch_screen.h:168
STROKE_PARAMS GetStroke() const override
Definition sch_shape.h:57
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
std::optional< SCH_SHEET_PATH > GetSheetPathByKIIDPath(const KIID_PATH &aPath, bool aIncludeLastSheet=true) const
Finds a SCH_SHEET_PATH that matches the provided KIID_PATH.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
bool HasRootInstance() const
Check to see if this sheet has a root sheet instance.
std::vector< SCH_FIELD > & GetFields()
Return a reference to the vector holding the sheet's fields.
Definition sch_sheet.h:91
bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
VECTOR2I GetSize() const
Definition sch_sheet.h:147
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:145
VECTOR2I GetPosition() const override
Definition sch_sheet.h:506
const SCH_SHEET_INSTANCE & GetRootInstance() const
Return the root sheet instance data.
KIGFX::COLOR4D GetBorderColor() const
Definition sch_sheet.h:153
bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flags.
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Definition sch_sheet.h:477
int GetBorderWidth() const
Definition sch_sheet.h:150
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition sch_sheet.h:243
const std::vector< SCH_SHEET_INSTANCE > & GetInstances() const
Definition sch_sheet.h:521
KIGFX::COLOR4D GetBackgroundColor() const
Definition sch_sheet.h:156
Schematic symbol object.
Definition sch_symbol.h:73
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
std::vector< std::unique_ptr< SCH_PIN > > & GetRawPins()
Definition sch_symbol.h:678
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition sch_symbol.h:133
bool UseLibIdLookup() const
Definition sch_symbol.h:180
wxString GetSchSymbolLibraryName() const
bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
VECTOR2I GetPosition() const override
Definition sch_symbol.h:900
const LIB_ID & GetLibId() const override
Definition sch_symbol.h:163
bool GetExcludedFromPosFiles(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool GetInstance(SCH_SYMBOL_INSTANCE &aInstance, const KIID_PATH &aSheetPath, bool aTestFromEnd=false) const
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
int GetOrientation() const override
Get the display symbol orientation.
virtual bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flag.
wxString GetPrefix() const
Definition sch_symbol.h:238
void SetRowHeight(int aRow, int aHeight)
Definition sch_table.h:138
const STROKE_PARAMS & GetSeparatorsStroke() const
Definition sch_table.h:76
void SetColCount(int aCount)
Definition sch_table.h:118
bool StrokeExternal() const
Definition sch_table.h:52
int GetRowHeight(int aRow) const
Definition sch_table.h:140
void SetColWidth(int aCol, int aWidth)
Definition sch_table.h:128
std::vector< SCH_TABLECELL * > GetCells() const
Definition sch_table.h:158
int GetColWidth(int aCol) const
Definition sch_table.h:130
const STROKE_PARAMS & GetBorderStroke() const
Definition sch_table.h:58
int GetColCount() const
Definition sch_table.h:119
bool StrokeHeaderSeparator() const
Definition sch_table.h:55
void DeleteMarkedCells()
Definition sch_table.h:183
SCH_TABLECELL * GetCell(int aRow, int aCol) const
Definition sch_table.h:148
bool StrokeColumns() const
Definition sch_table.h:98
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition sch_table.h:232
bool StrokeRows() const
Definition sch_table.h:101
int GetRowCount() const
Definition sch_table.h:121
int GetMarginBottom() const
Definition sch_textbox.h:82
int GetMarginLeft() const
Definition sch_textbox.h:79
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
int GetMarginRight() const
Definition sch_textbox.h:81
int GetMarginTop() const
Definition sch_textbox.h:80
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Definition sch_text.h:86
VECTOR2I GetPosition() const override
Definition sch_text.h:143
void saveTextBox(SCH_TEXTBOX *aTextBox)
void saveBitmap(const SCH_BITMAP &aBitmap)
void SaveSchematicFile(const wxString &aFileName, SCH_SHEET *aSheet, SCHEMATIC *aSchematic)
void saveText(SCH_TEXT *aText)
static constexpr int FORMAT_VERSION
void saveTable(SCH_TABLE *aTable)
void Format(SCH_SHEET *aSheet)
void SaveSymbolLibrary(const wxString &aFileName, const std::vector< LIB_SYMBOL * > &aSymbols)
OUTPUTFORMATTER * m_out
void saveSymbol(SCH_SYMBOL *aSymbol, const SCHEMATIC &aSchematic, const SCH_SHEET_LIST &aSheetList, bool aForClipboard, const SCH_SHEET_PATH *aRelativePath=nullptr)
void saveGroup(SCH_GROUP *aGroup)
void saveLine(SCH_LINE *aLine)
SCHEMATIC * m_schematic
void saveRuleArea(SCH_RULE_AREA *aRuleArea)
static constexpr int SYMBOL_LIB_VERSION
void saveInstances(const std::vector< SCH_SHEET_INSTANCE > &aInstances)
void saveSheet(SCH_SHEET *aSheet, const SCH_SHEET_LIST &aSheetList)
void saveJunction(SCH_JUNCTION *aJunction)
void saveBusEntry(SCH_BUS_ENTRY_BASE *aBusEntry)
void saveNoConnect(SCH_NO_CONNECT *aNoConnect)
void saveField(SCH_FIELD *aField)
void saveShape(SCH_SHAPE *aShape)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool IsClosed() const override
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
const std::vector< VECTOR2I > & CPoints() const
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int OutlineCount() const
Return the number of outlines in the set.
Simple container to manage line stroke parameters.
void SetWidth(int aWidth)
bool GetExcludedFromPosFiles(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Definition symbol.h:231
int GetPinNameOffset() const
Definition symbol.h:163
virtual bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Definition symbol.h:201
virtual bool GetShowPinNames() const
Definition symbol.h:169
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Definition symbol.h:216
virtual bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Definition symbol.h:186
virtual bool GetShowPinNumbers() const
Definition symbol.h:175
wxString wx_str() const
Definition utf8.cpp:41
#define DEFAULT_PIN_NAME_OFFSET
The offset of the pin name string from the end of the pin in mils.
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:448
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:450
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:453
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:452
FILL_T
Definition eda_fill.h:29
@ FILLED_WITH_COLOR
Definition eda_fill.h:33
@ NO_FILL
Definition eda_fill.h:30
@ REVERSE_HATCH
Definition eda_fill.h:35
@ HATCH
Definition eda_fill.h:34
@ FILLED_WITH_BG_BODYCOLOR
Definition eda_fill.h:32
@ FILLED_SHAPE
Fill with object color.
Definition eda_fill.h:31
@ CROSS_HATCH
Definition eda_fill.h:36
#define IS_CHANGED
Item was edited, and modified.
#define STRUCT_DELETED
flag indication structures to be erased
#define SKIP_STRUCT
flag indicating that the structure should be ignored
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:57
#define DEFAULT_SIZE_TEXT
This is the "default-of-the-default" hardcoded text size; individual application define their own def...
Definition eda_text.h:84
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition idf_helpers.h:37
KIID niluuid(0)
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
Definition layer_id.cpp:31
@ LAYER_WIRE
Definition layer_ids.h:474
@ LAYER_NOTES
Definition layer_ids.h:489
@ LAYER_BUS
Definition layer_ids.h:475
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:92
KICOMMON_API std::string FormatAngle(const EDA_ANGLE &aAngle)
Convert aAngle from board units to a string appropriate for writing to file.
KICOMMON_API std::string FormatInternalUnits(const EDA_IU_SCALE &aIuScale, int aValue, EDA_DATA_TYPE aDataType=EDA_DATA_TYPE::DISTANCE)
Converts aValue from internal units to a string appropriate for writing to file.
void FormatBool(OUTPUTFORMATTER *aOut, const wxString &aKey, bool aValue)
void FormatTitle(OUTPUTFORMATTER *aOut, const TITLE_BLOCK &aTitle)
bool IsDefaultTextV10(const EDA_TEXT &aText)
void FormatStreamData(OUTPUTFORMATTER &aOut, const wxStreamBuffer &aStream)
void FormatUuid(OUTPUTFORMATTER *aOut, const KIID &aUuid)
void FormatTextV10(OUTPUTFORMATTER *aOut, const EDA_TEXT &aText, const EDA_IU_SCALE &aScale, int aControlBits)
void FormatStroke(OUTPUTFORMATTER *aOut, const STROKE_PARAMS &aStroke, const EDA_IU_SCALE &aScale)
UTF8 FormatLibId(const LIB_ID &aId)
void FormatPageV10(OUTPUTFORMATTER *aOut, const PAGE_INFO &aPage)
void FormatEmbeddedFilesV10(OUTPUTFORMATTER &aOut, const EMBEDDED_FILES &aFiles, bool aWriteData)
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition pin_type.h:32
@ PT_INPUT
usual pin input: must be connected
Definition pin_type.h:33
@ PT_NC
not connected (must be left open)
Definition pin_type.h:46
@ PT_OUTPUT
usual output
Definition pin_type.h:34
@ PT_TRISTATE
tri state bus pin
Definition pin_type.h:36
@ PT_NIC
not internally connected (may be connected to anything)
Definition pin_type.h:40
@ PT_BIDI
input or output (like port for a microprocessor)
Definition pin_type.h:35
@ PT_OPENEMITTER
pin type open emitter
Definition pin_type.h:45
@ PT_POWER_OUT
output of a regulator: intended to be connected to power input pins
Definition pin_type.h:43
@ PT_OPENCOLLECTOR
pin type open collector
Definition pin_type.h:44
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
Definition pin_type.h:42
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
Definition pin_type.h:41
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
Definition pin_type.h:39
PIN_ORIENTATION
The symbol library pin object orientations.
Definition pin_type.h:101
@ PIN_UP
The pin extends upwards from the connection point: Probably on the bottom side of the symbol.
Definition pin_type.h:123
@ PIN_RIGHT
The pin extends rightwards from the connection point.
Definition pin_type.h:107
@ PIN_LEFT
The pin extends leftwards from the connection point: Probably on the right side of the symbol.
Definition pin_type.h:114
@ PIN_DOWN
The pin extends downwards from the connection: Probably on the top side of the symbol.
Definition pin_type.h:131
GRAPHIC_PINSHAPE
Definition pin_type.h:80
Class to handle a set of SCH_ITEMs.
EDA_ANGLE getPinAngle(PIN_ORIENTATION aOrientation)
void formatArc(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aArc, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid, bool aLocked)
void formatCircle(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aCircle, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid, bool aLocked)
const char * getSheetPinShapeToken(LABEL_FLAG_SHAPE aShape)
void formatRect(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aRect, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid, bool aLocked)
const char * getPinElectricalTypeToken(ELECTRICAL_PINTYPE aType)
const char * getTextTypeToken(KICAD_T aType)
void formatBezier(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aBezier, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid, bool aLocked)
std::string formatIU(const int &aValue)
void formatPoly(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aPolyLine, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid, bool aLocked)
EDA_ANGLE getSheetPinAngle(SHEET_SIDE aSide)
void formatFill(OUTPUTFORMATTER *aFormatter, FILL_T aFillMode, const COLOR4D &aFillColor)
Fill token formatting helper.
const char * getPinShapeToken(GRAPHIC_PINSHAPE aShape)
static const char * emptyString
AUTOPLACE_ALGO
Definition sch_item.h:73
@ AUTOPLACE_MANUAL
Definition sch_item.h:76
@ AUTOPLACE_AUTO
Definition sch_item.h:75
LABEL_FLAG_SHAPE
Label and flag shapes used with text objects.
Definition sch_label.h:97
@ L_BIDI
Definition sch_label.h:100
@ L_TRISTATE
Definition sch_label.h:101
@ L_UNSPECIFIED
Definition sch_label.h:102
@ F_DOT
Definition sch_label.h:105
@ F_ROUND
Definition sch_label.h:106
@ L_OUTPUT
Definition sch_label.h:99
@ F_DIAMOND
Definition sch_label.h:107
@ L_INPUT
Definition sch_label.h:98
@ F_RECTANGLE
Definition sch_label.h:108
SHEET_SIDE
Define the edge of the sheet that the sheet pin is positioned.
std::string toUTFTildaText(const wxString &txt)
Convert a wxString to UTF8 and replace any control characters with a ~, where a control character is ...
static const char * getTextTypeToken(KICAD_T aType)
static EDA_ANGLE getSheetPinAngle(SHEET_SIDE aSide)
static void formatFill(OUTPUTFORMATTER *aFormatter, FILL_T aFillMode, const COLOR4D &aFillColor)
static void formatArc(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aArc, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid=niluuid)
static void formatPoly(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aPolyLine, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid=niluuid)
static EDA_ANGLE getPinAngle(PIN_ORIENTATION aOrientation)
static void formatCircle(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aCircle, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid=niluuid)
static void libSaveField(SCH_FIELD *aField, OUTPUTFORMATTER &aFormatter)
static void libSaveSymbol(LIB_SYMBOL *aSymbol, OUTPUTFORMATTER &aFormatter, const wxString &aLibName=wxEmptyString, bool aIncludeData=true)
static const char * getPinShapeToken(GRAPHIC_PINSHAPE aShape)
static void formatBezier(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aBezier, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid=niluuid)
static std::string formatIU(const int &aValue)
static void libSaveText(SCH_TEXT *aText, OUTPUTFORMATTER &aFormatter)
static void formatRect(OUTPUTFORMATTER *aFormatter, EDA_SHAPE *aRect, bool aIsPrivate, const STROKE_PARAMS &aStroke, FILL_T aFillMode, const COLOR4D &aFillColor, bool aInvertY, const KIID &aUuid=niluuid)
static void libSaveTextBox(SCH_TEXTBOX *aTextBox, OUTPUTFORMATTER &aFormatter)
static void libSaveDcmInfoAsFields(LIB_SYMBOL *aSymbol, OUTPUTFORMATTER &aFormatter)
static const char * getPinElectricalTypeToken(ELECTRICAL_PINTYPE aType)
static void libSavePin(SCH_PIN *aPin, OUTPUTFORMATTER &aFormatter)
static void libSaveSymbolDrawItem(SCH_ITEM *aItem, OUTPUTFORMATTER &aFormatter)
static const char * getSheetPinShapeToken(LABEL_FLAG_SHAPE aShape)
static wxString projectKey(const wxString &aFullPath)
const int scale
std::string FormatDouble2Str(double aValue)
Print a float number without using scientific notation and no trailing 0 This function is intended in...
std::string EscapedUTF8(const wxString &aString)
Return an 8 bit UTF8 string given aString in Unicode form.
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_NO_SPACE
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
@ SYM_ORIENT_270
Definition symbol.h:39
@ SYM_MIRROR_Y
Definition symbol.h:41
@ SYM_ORIENT_180
Definition symbol.h:38
@ SYM_MIRROR_X
Definition symbol.h:40
@ SYM_ORIENT_90
Definition symbol.h:37
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ USER
The field ID hasn't been set yet; field is invalid.
@ REFERENCE
Field Reference of part, i.e. "IC21".
std::string path
KIBIS_PIN * pin
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70
@ SCH_GROUP_T
Definition typeinfo.h:169
@ SCH_TABLE_T
Definition typeinfo.h:161
@ SCH_LINE_T
Definition typeinfo.h:159
@ SCH_NO_CONNECT_T
Definition typeinfo.h:156
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_TABLECELL_T
Definition typeinfo.h:162
@ SCH_FIELD_T
Definition typeinfo.h:146
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:167
@ SCH_LABEL_T
Definition typeinfo.h:163
@ SCH_SHEET_T
Definition typeinfo.h:171
@ SCH_MARKER_T
Definition typeinfo.h:154
@ SCH_SHAPE_T
Definition typeinfo.h:145
@ SCH_RULE_AREA_T
Definition typeinfo.h:166
@ SCH_HIER_LABEL_T
Definition typeinfo.h:165
@ SCH_BUS_BUS_ENTRY_T
Definition typeinfo.h:158
@ SCH_TEXT_T
Definition typeinfo.h:147
@ SCH_BUS_WIRE_ENTRY_T
Definition typeinfo.h:157
@ SCH_BITMAP_T
Definition typeinfo.h:160
@ SCH_TEXTBOX_T
Definition typeinfo.h:148
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:164
@ SCH_JUNCTION_T
Definition typeinfo.h:155
@ SCH_PIN_T
Definition typeinfo.h:149
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708