KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_easyedapro_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) 2023 Alex Shvartzkop <[email protected]>
5 * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
27
28#include <core/map_helpers.h>
29
30#include <sch_io_mgr.h>
31#include <schematic.h>
32#include <sch_sheet.h>
33#include <sch_sheet_pin.h>
34#include <sch_line.h>
35#include <sch_bitmap.h>
36#include <lib_shape.h>
37#include <lib_text.h>
38#include <sch_no_connect.h>
39#include <sch_label.h>
40#include <sch_junction.h>
41#include <sch_edit_frame.h>
42#include <sch_shape.h>
43#include <sch_bus_entry.h>
44#include <string_utils.h>
45#include <bezier_curves.h>
46#include <wx/base64.h>
47#include <wx/url.h>
48#include <wx/mstream.h>
49#include <gfx_import_utils.h>
53
54
56 PROGRESS_REPORTER* aProgressReporter )
57{
58 m_schematic = aSchematic;
59}
60
61
63{
64}
65
66
67double SCH_EASYEDAPRO_PARSER::Convert( wxString aValue )
68{
69 double value = 0;
70
71 if( !aValue.ToCDouble( &value ) )
72 THROW_IO_ERROR( wxString::Format( _( "Failed to parse value: '%s'" ), aValue ) );
73
74 return value;
75}
76
77
78double SCH_EASYEDAPRO_PARSER::SizeToKi( wxString aValue )
79{
80 return ScaleSize( Convert( aValue ) );
81}
82
83
84static LINE_STYLE ConvertStrokeStyle( int aStyle )
85{
86 if( aStyle == 0 )
87 return LINE_STYLE::SOLID;
88 else if( aStyle == 1 )
89 return LINE_STYLE::DASH;
90 else if( aStyle == 2 )
91 return LINE_STYLE::DOT;
92 else if( aStyle == 3 )
94
96}
97
98
99template <typename T>
100void SCH_EASYEDAPRO_PARSER::ApplyFontStyle( const std::map<wxString, nlohmann::json>& fontStyles,
101 T& text, const wxString& styleStr )
102{
103 auto it = fontStyles.find( styleStr );
104
105 if( it == fontStyles.end() )
106 return;
107
108 nlohmann::json style = it->second;
109
110 if( !style.is_array() )
111 return;
112
113 if( style.size() < 12 )
114 return;
115
116 if( style.at( 3 ).is_string() )
117 {
118 COLOR4D color( style.at( 3 ).get<wxString>() );
119 text->SetTextColor( color );
120 }
121
122 if( style.at( 4 ).is_string() )
123 {
124 wxString fontname = ( style.at( 4 ) );
125
126 if( !fontname.IsSameAs( wxS( "default" ), false ) )
127 text->SetFont( KIFONT::FONT::GetFont( fontname ) );
128 }
129
130 if( style.at( 5 ).is_number() )
131 {
132 double size = style.at( 5 ).get<double>() * 0.5;
133 text->SetTextSize( VECTOR2I( ScaleSize( size ), ScaleSize( size ) ) );
134 }
135
136 if( style.at( 10 ).is_number() )
137 {
138 int valign = style.at( 10 );
139
140 if( !text->GetText().Contains( wxS( "\n" ) ) )
141 {
142 if( valign == 0 )
143 text->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
144 else if( valign == 1 )
145 text->SetVertJustify( GR_TEXT_V_ALIGN_CENTER );
146 else if( valign == 2 )
147 text->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
148 }
149 else
150 {
151 text->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
152 // TODO: align by first line
153 }
154 }
155 else
156 {
157 text->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
158 }
159
160 if( style.at( 11 ).is_number() )
161 {
162 int halign = style.at( 11 );
163
164 if( halign == 0 )
165 text->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
166 else if( halign == 1 )
167 text->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
168 else if( halign == 2 )
169 text->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
170 }
171 else
172 {
173 text->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
174 }
175}
176
177
178template <typename T>
179void SCH_EASYEDAPRO_PARSER::ApplyLineStyle( const std::map<wxString, nlohmann::json>& lineStyles,
180 T& shape, const wxString& styleStr )
181{
182 auto it = lineStyles.find( styleStr );
183
184 if( it == lineStyles.end() )
185 return;
186
187 nlohmann::json style = it->second;
188
189 if( !style.is_array() )
190 return;
191
192 if( style.size() < 6 )
193 return;
194
195 STROKE_PARAMS stroke = shape->GetStroke();
196
197 if( style.at( 2 ).is_string() )
198 {
199 wxString colorStr = style.at( 2 ).get<wxString>();
200
201 if( !colorStr.empty() && colorStr.starts_with( wxS( "#" ) ) )
202 {
203 COLOR4D color( colorStr );
204 stroke.SetColor( color );
205 }
206 }
207
208 if( style.at( 3 ).is_number() )
209 {
210 int dashStyle = style.at( 3 );
211 stroke.SetLineStyle( ConvertStrokeStyle( dashStyle ) );
212 }
213
214 if( style.at( 5 ).is_number() )
215 {
216 double thickness = style.at( 5 );
217 stroke.SetWidth( ScaleSize( thickness ) );
218 }
219
220 shape->SetStroke( stroke );
221}
222
223
224template <typename T>
225void SCH_EASYEDAPRO_PARSER::ApplyAttrToField( const std::map<wxString, nlohmann::json>& fontStyles,
226 T* field, const EASYEDAPRO::SCH_ATTR& aAttr,
227 bool aIsSym, bool aToSym, SCH_SYMBOL* aParent )
228{
229 EDA_TEXT* text = static_cast<EDA_TEXT*>( field );
230
231 text->SetVisible( aAttr.keyVisible || aAttr.valVisible );
232 text->SetText( aAttr.value );
233
234 field->SetNameShown( aAttr.keyVisible );
235
236 if( aAttr.position )
237 {
238 field->SetPosition( !aIsSym ? ScalePos( *aAttr.position )
239 : ScalePosSym( *aAttr.position ) );
240 }
241
242 ApplyFontStyle( fontStyles, text, aAttr.fontStyle );
243
244 auto parent = aParent;
245 if( parent && parent->Type() == SCH_SYMBOL_T )
246 {
247 int orient = static_cast<SCH_SYMBOL*>( parent )->GetOrientation();
248
249 if( orient == SYM_ORIENT_180 )
250 {
251 text->SetVertJustify( static_cast<GR_TEXT_V_ALIGN_T>( -text->GetVertJustify() ) );
252 text->SetHorizJustify( static_cast<GR_TEXT_H_ALIGN_T>( -text->GetHorizJustify() ) );
253 }
254 else if( orient == SYM_MIRROR_X + SYM_ORIENT_0 )
255 {
256 text->SetVertJustify( static_cast<GR_TEXT_V_ALIGN_T>( -text->GetVertJustify() ) );
257 }
258 else if( orient == SYM_MIRROR_Y + SYM_ORIENT_0 )
259 {
260 text->SetHorizJustify( static_cast<GR_TEXT_H_ALIGN_T>( -text->GetHorizJustify() ) );
261 }
262 else if( orient == SYM_MIRROR_Y + SYM_ORIENT_180 )
263 {
264 text->SetHorizJustify( static_cast<GR_TEXT_H_ALIGN_T>( text->GetHorizJustify() ) );
265 }
266 else if( orient == SYM_ORIENT_90 )
267 {
268 text->SetTextAngle( ANGLE_VERTICAL );
269 text->SetVertJustify( static_cast<GR_TEXT_V_ALIGN_T>( -text->GetVertJustify() ) );
270 text->SetHorizJustify( static_cast<GR_TEXT_H_ALIGN_T>( -text->GetHorizJustify() ) );
271 }
272 if( orient == SYM_ORIENT_270 )
273 {
274 text->SetTextAngle( ANGLE_VERTICAL );
275 }
276 else if( orient == SYM_MIRROR_X + SYM_ORIENT_90 )
277 {
278 text->SetTextAngle( ANGLE_VERTICAL );
279 text->SetVertJustify( static_cast<GR_TEXT_V_ALIGN_T>( -text->GetVertJustify() ) );
280 text->SetHorizJustify( static_cast<GR_TEXT_H_ALIGN_T>( -text->GetHorizJustify() ) );
281 }
282 else if( orient == SYM_MIRROR_X + SYM_ORIENT_270 )
283 {
284 text->SetTextAngle( ANGLE_VERTICAL );
285 text->SetVertJustify( static_cast<GR_TEXT_V_ALIGN_T>( -text->GetVertJustify() ) );
286 }
287 else if( orient == SYM_MIRROR_Y + SYM_ORIENT_90 )
288 {
289 text->SetTextAngle( ANGLE_VERTICAL );
290 text->SetHorizJustify( static_cast<GR_TEXT_H_ALIGN_T>( -text->GetHorizJustify() ) );
291 }
292 else if( orient == SYM_MIRROR_Y + SYM_ORIENT_270 )
293 {
294 text->SetHorizJustify( static_cast<GR_TEXT_H_ALIGN_T>( text->GetHorizJustify() ) );
295 }
296
297 if( aAttr.rotation == 90 )
298 {
299 if( text->GetTextAngle() == ANGLE_HORIZONTAL )
300 text->SetTextAngle( ANGLE_VERTICAL );
301 else
302 text->SetTextAngle( ANGLE_HORIZONTAL );
303
304 if( orient == SYM_ORIENT_90 )
305 {
306 text->SetVertJustify( static_cast<GR_TEXT_V_ALIGN_T>( -text->GetVertJustify() ) );
307 text->SetHorizJustify( static_cast<GR_TEXT_H_ALIGN_T>( -text->GetHorizJustify() ) );
308 }
309 if( orient == SYM_ORIENT_270 )
310 {
311 text->SetVertJustify( static_cast<GR_TEXT_V_ALIGN_T>( -text->GetVertJustify() ) );
312 text->SetHorizJustify( static_cast<GR_TEXT_H_ALIGN_T>( -text->GetHorizJustify() ) );
313 }
314 else if( orient == SYM_MIRROR_X + SYM_ORIENT_90 )
315 {
316 text->SetVertJustify( static_cast<GR_TEXT_V_ALIGN_T>( -text->GetVertJustify() ) );
317 }
318 }
319 }
320}
321
322
323EASYEDAPRO::SYM_INFO SCH_EASYEDAPRO_PARSER::ParseSymbol( const std::vector<nlohmann::json>& aLines )
324{
325 EASYEDAPRO::SYM_INFO symInfo;
326
327 std::unique_ptr<LIB_SYMBOL> ksymbolPtr = std::make_unique<LIB_SYMBOL>( wxEmptyString );
328 LIB_SYMBOL* ksymbol = ksymbolPtr.get();
329
330 std::map<wxString, nlohmann::json> lineStyles;
331 std::map<wxString, nlohmann::json> fontStyles;
332 std::map<wxString, int> partUnits;
333
334 std::map<int, std::map<wxString, EASYEDAPRO::SCH_ATTR>> unitAttributes;
335 std::map<int, std::map<wxString, std::vector<nlohmann::json>>> unitParentedLines;
336
337 int totalUnits = 0;
338
339 for( const nlohmann::json& line : aLines )
340 {
341 wxString type = line.at( 0 );
342
343 if( type == wxS( "LINESTYLE" ) )
344 lineStyles[line.at( 1 )] = line;
345 else if( type == wxS( "FONTSTYLE" ) )
346 fontStyles[line.at( 1 )] = line;
347 else if( type == wxS( "PART" ) )
348 partUnits[line.at( 1 )] = ++totalUnits;
349 }
350
351 symInfo.partUnits = partUnits;
352 ksymbol->SetUnitCount( totalUnits, false );
353
354 int currentUnit = 1;
355
356 for( const nlohmann::json& line : aLines )
357 {
358 wxString type = line.at( 0 );
359
360 if( type == wxS( "PART" ) )
361 {
362 currentUnit = partUnits.at( line.at( 1 ) );
363 }
364 else if( type == wxS( "RECT" ) )
365 {
366 VECTOR2D start( line.at( 2 ), line.at( 3 ) );
367 VECTOR2D end( line.at( 4 ), line.at( 5 ) );
368 wxString styleStr = line.at( 9 );
369
370 std::unique_ptr<LIB_SHAPE> rect =
371 std::make_unique<LIB_SHAPE>( ksymbol, SHAPE_T::RECTANGLE );
372
373 rect->SetStart( ScalePosSym( start ) );
374 rect->SetEnd( ScalePosSym( end ) );
375
376 rect->SetUnit( currentUnit );
377 ApplyLineStyle( lineStyles, rect, styleStr );
378
379 ksymbol->AddDrawItem( rect.release() );
380 }
381 else if( type == wxS( "CIRCLE" ) )
382 {
383 VECTOR2D center( line.at( 2 ), line.at( 3 ) );
384 double radius = line.at( 4 );
385 wxString styleStr = line.at( 5 );
386
387 std::unique_ptr<LIB_SHAPE> circle =
388 std::make_unique<LIB_SHAPE>( ksymbol, SHAPE_T::CIRCLE );
389
390 circle->SetCenter( ScalePosSym( center ) );
391 circle->SetEnd( circle->GetCenter() + VECTOR2I( ScaleSize( radius ), 0 ) );
392
393 circle->SetUnit( currentUnit );
394 ApplyLineStyle( lineStyles, circle, styleStr );
395
396 ksymbol->AddDrawItem( circle.release() );
397 }
398 else if( type == wxS( "ARC" ) )
399 {
400 VECTOR2D start( line.at( 2 ), line.at( 3 ) );
401 VECTOR2D mid( line.at( 4 ), line.at( 5 ) );
402 VECTOR2D end( line.at( 6 ), line.at( 7 ) );
403 wxString styleStr = line.at( 8 );
404
405 VECTOR2D kstart = ScalePosSym( start );
406 VECTOR2D kmid = ScalePosSym( mid );
407 VECTOR2D kend = ScalePosSym( end );
408
409 VECTOR2D kcenter = CalcArcCenter( kstart, kmid, kend );
410
411 std::unique_ptr<LIB_SHAPE> shape = std::make_unique<LIB_SHAPE>( ksymbol, SHAPE_T::ARC );
412
413 shape->SetStart( kstart );
414 shape->SetEnd( kend );
415 shape->SetCenter( kcenter );
416
417 if( SEG( start, end ).Side( mid ) != SEG( kstart, kend ).Side( shape->GetArcMid() ) )
418 {
419 shape->SetStart( kend );
420 shape->SetEnd( kstart );
421 }
422
423 shape->SetUnit( currentUnit );
424 ApplyLineStyle( lineStyles, shape, styleStr );
425
426 ksymbol->AddDrawItem( shape.release() );
427 }
428 else if( type == wxS( "POLY" ) )
429 {
430 std::vector<double> points = line.at( 2 );
431 wxString styleStr = line.at( 4 );
432
433 std::unique_ptr<LIB_SHAPE> shape =
434 std::make_unique<LIB_SHAPE>( ksymbol, SHAPE_T::POLY );
435
436 for( size_t i = 1; i < points.size(); i += 2 )
437 {
438 shape->AddPoint( ScalePosSym( VECTOR2D( points[i - 1], points[i] ) ) );
439 }
440
441 shape->SetUnit( currentUnit );
442 ApplyLineStyle( lineStyles, shape, styleStr );
443
444 ksymbol->AddDrawItem( shape.release() );
445 }
446 else if( type == wxS( "TEXT" ) )
447 {
448 VECTOR2D pos( line.at( 2 ), line.at( 3 ) );
449 double angle = line.at( 4 );
450 wxString textStr = line.at( 5 );
451 wxString fontStyleStr = line.at( 6 );
452
453 std::unique_ptr<LIB_TEXT> text = std::make_unique<LIB_TEXT>( ksymbol );
454
455 text->SetPosition( ScalePosSym( pos ) );
456 text->SetText( UnescapeHTML( textStr ) );
457
458 text->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
459 text->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
460
461 text->SetTextAngleDegrees( angle );
462
463 text->SetUnit( currentUnit );
464 ApplyFontStyle( fontStyles, text, fontStyleStr );
465
466 ksymbol->AddDrawItem( text.release() );
467 }
468 else if( type == wxS( "OBJ" ) )
469 {
470 VECTOR2D start, size;
471 wxString mimeType, data;
472 double angle = 0;
473 int upsideDown = 0;
474
475 if( line.at( 3 ).is_number() )
476 {
477 start = VECTOR2D( line.at( 3 ), line.at( 4 ) );
478 size = VECTOR2D( line.at( 5 ), line.at( 6 ) );
479 angle = line.at( 7 );
480 upsideDown = line.at( 8 );
481
482 wxString imageUrl = line.at( 9 );
483
484 if( imageUrl.BeforeFirst( ':' ) == wxS( "data" ) )
485 {
486 wxArrayString paramsArr =
487 wxSplit( imageUrl.AfterFirst( ':' ).BeforeFirst( ',' ), ';', '\0' );
488
489 data = imageUrl.AfterFirst( ',' );
490
491 if( paramsArr.size() > 0 )
492 {
493 mimeType = paramsArr[0];
494 }
495 }
496 }
497 else if( line.at( 3 ).is_string() )
498 {
499 mimeType = line.at( 3 ).get<wxString>().BeforeFirst( ';' );
500
501 start = VECTOR2D( line.at( 4 ), line.at( 5 ) );
502 size = VECTOR2D( line.at( 6 ), line.at( 7 ) );
503 angle = line.at( 8 );
504 data = line.at( 9 ).get<wxString>();
505 }
506
507 if( mimeType.empty() || data.empty() )
508 continue;
509
510 wxMemoryBuffer buf = wxBase64Decode( data );
511
512 if( mimeType == wxS( "image/svg+xml" ) )
513 {
514 VECTOR2D offset = ScalePosSym( start );
515
516 SVG_IMPORT_PLUGIN svgImportPlugin;
517 GRAPHICS_IMPORTER_LIB_SYMBOL libsymImporter( ksymbol, 0 );
518
519 svgImportPlugin.SetImporter( &libsymImporter );
520 svgImportPlugin.LoadFromMemory( buf );
521
522 VECTOR2D imSize( svgImportPlugin.GetImageWidth(),
523 svgImportPlugin.GetImageHeight() );
524
525 VECTOR2D pixelScale( schIUScale.IUTomm( ScaleSize( size.x ) ) / imSize.x,
526 schIUScale.IUTomm( -ScaleSize( size.y ) ) / imSize.y );
527
528 if( upsideDown )
529 pixelScale.y *= -1;
530
531 libsymImporter.SetScale( pixelScale );
532
533 VECTOR2D offsetMM( schIUScale.IUTomm( offset.x ), schIUScale.IUTomm( offset.y ) );
534
535 libsymImporter.SetImportOffsetMM( offsetMM );
536
537 svgImportPlugin.Import();
538
539 // TODO: rotation
540 for( std::unique_ptr<EDA_ITEM>& item : libsymImporter.GetItems() )
541 ksymbol->AddDrawItem( static_cast<LIB_ITEM*>( item.release() ) );
542 }
543 else
544 {
545 wxMemoryInputStream memis( buf.GetData(), buf.GetDataLen() );
546
547 wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
548 & ~wxImage::Load_Verbose );
549 wxImage img;
550 if( img.LoadFile( memis, mimeType ) )
551 {
552 int dimMul = img.GetWidth() * img.GetHeight();
553 double maxPixels = 30000;
554
555 if( dimMul > maxPixels )
556 {
557 double scale = sqrt( maxPixels / dimMul );
558 img.Rescale( img.GetWidth() * scale, img.GetHeight() * scale );
559 }
560
561 VECTOR2D pixelScale( ScaleSize( size.x ) / img.GetWidth(),
562 -ScaleSize( size.y ) / img.GetHeight() );
563
564 // TODO: rotation
565 ConvertImageToLibShapes( ksymbol, 0, img, pixelScale, ScalePosSym( start ) );
566 }
567 }
568 }
569 else if( type == wxS( "HEAD" ) )
570 {
571 symInfo.head = line;
572 }
573 else if( type == wxS( "PIN" ) )
574 {
575 wxString pinId = line.at( 1 );
576 unitParentedLines[currentUnit][pinId].push_back( line );
577 }
578 else if( type == wxS( "ATTR" ) )
579 {
580 wxString parentId = line.at( 2 );
581
582 if( parentId.empty() )
583 {
584 EASYEDAPRO::SCH_ATTR attr = line;
585 unitAttributes[currentUnit].emplace( attr.key, attr );
586 }
587 else
588 {
589 unitParentedLines[currentUnit][parentId].push_back( line );
590 }
591 }
592 }
593
596 {
597 ksymbol->SetPower();
598 ksymbol->GetReferenceField().SetText( wxS( "#PWR" ) );
599 ksymbol->GetReferenceField().SetVisible( false );
600 ksymbol->SetKeyWords( wxS( "power-flag" ) );
601 ksymbol->SetShowPinNames( false );
602 ksymbol->SetShowPinNumbers( false );
603
604 if( auto globalNetAttr = get_opt( unitAttributes[1], wxS( "Global Net Name" ) ) )
605 {
606 ApplyAttrToField( fontStyles, &ksymbol->GetValueField(), *globalNetAttr, true, true );
607
608 wxString globalNetname = globalNetAttr->value;
609
610 if( !globalNetname.empty() )
611 {
612 ksymbol->SetDescription( wxString::Format(
613 _( "Power symbol creates a global label with name '%s'" ),
614 globalNetname ) );
615 }
616 }
617 }
618 else
619 {
620 auto designatorAttr = get_opt( unitAttributes[1], wxS( "Designator" ) );
621
622 if( designatorAttr && !designatorAttr->value.empty() )
623 {
624 wxString symbolPrefix = designatorAttr->value;
625
626 if( !symbolPrefix.EndsWith( wxS( "?" ) ) )
627 symbolPrefix += wxS( "?" );
628
629 ksymbol->GetReferenceField().SetText( symbolPrefix );
630 }
631 }
632
633 for( auto& [unitId, parentedLines] : unitParentedLines )
634 {
635 for( auto& [pinId, lines] : parentedLines )
636 {
637 std::optional<EASYEDAPRO::SYM_PIN> epin;
638 std::map<wxString, EASYEDAPRO::SCH_ATTR> pinAttributes;
639
640 for( const nlohmann::json& line : lines )
641 {
642 wxString type = line.at( 0 );
643
644 if( type == wxS( "ATTR" ) )
645 {
646 EASYEDAPRO::SCH_ATTR attr = line;
647 pinAttributes.emplace( attr.key, attr );
648 }
649 else if( type == wxS( "PIN" ) )
650 {
651 epin = line;
652 }
653 }
654
655 if( !epin )
656 continue;
657
658 EASYEDAPRO::PIN_INFO pinInfo;
659 pinInfo.pin = *epin;
660
661 std::unique_ptr<LIB_PIN> pin = std::make_unique<LIB_PIN>( ksymbol );
662
663 pin->SetUnit( unitId );
664
665 pin->SetLength( ScaleSize( epin->length ) );
666 pin->SetPosition( ScalePosSym( epin->position ) );
667
668 PIN_ORIENTATION orient = PIN_ORIENTATION::PIN_RIGHT;
669
670 if( epin->rotation == 0 )
671 orient = PIN_ORIENTATION::PIN_RIGHT;
672 if( epin->rotation == 90 )
673 orient = PIN_ORIENTATION::PIN_UP;
674 if( epin->rotation == 180 )
675 orient = PIN_ORIENTATION::PIN_LEFT;
676 if( epin->rotation == 270 )
677 orient = PIN_ORIENTATION::PIN_DOWN;
678
679 pin->SetOrientation( orient );
680
682 {
683 pin->SetName( ksymbol->GetName() );
684 //pin->SetVisible( false );
685 }
686 else if( auto pinNameAttr = get_opt( pinAttributes, "NAME" ) )
687 {
688 pin->SetName( pinNameAttr->value );
689 pinInfo.name = pinNameAttr->value;
690
691 if( !pinNameAttr->valVisible )
692 pin->SetNameTextSize( schIUScale.MilsToIU( 1 ) );
693 }
694
695 if( auto pinNumAttr = get_opt( pinAttributes, "NUMBER" ) )
696 {
697 pin->SetNumber( pinNumAttr->value );
698 pinInfo.number = pinNumAttr->value;
699
700 if( !pinNumAttr->valVisible )
701 pin->SetNumberTextSize( schIUScale.MilsToIU( 1 ) );
702 }
703
705 {
706 pin->SetType( ELECTRICAL_PINTYPE::PT_POWER_IN );
707 }
708 else if( auto pinTypeAttr = get_opt( pinAttributes, "Pin Type" ) )
709 {
710 if( pinTypeAttr->value == wxS( "IN" ) )
711 pin->SetType( ELECTRICAL_PINTYPE::PT_INPUT );
712 if( pinTypeAttr->value == wxS( "OUT" ) )
713 pin->SetType( ELECTRICAL_PINTYPE::PT_OUTPUT );
714 if( pinTypeAttr->value == wxS( "BI" ) )
715 pin->SetType( ELECTRICAL_PINTYPE::PT_BIDI );
716 }
717
718 if( get_opt( pinAttributes, "NO_CONNECT" ) )
719 pin->SetType( ELECTRICAL_PINTYPE::PT_NC );
720
721 if( pin->GetNumberTextSize() * int( pin->GetNumber().size() ) > pin->GetLength() )
722 pin->SetNumberTextSize( pin->GetLength() / pin->GetNumber().size() );
723
724 symInfo.pins.push_back( pinInfo );
725 ksymbol->AddDrawItem( pin.release() );
726 }
727 }
728
729 symInfo.symbolAttr = get_opt( unitAttributes[1], "Symbol" ); // TODO: per-unit
730
731 /*BOX2I bbox = ksymbol->GetBodyBoundingBox( 0, 0, true, true );
732 bbox.Inflate( schIUScale.MilsToIU( 10 ) );*/
733
734 /*ksymbol->GetReferenceField().SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
735 ksymbol->GetReferenceField().SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
736 ksymbol->GetReferenceField().SetPosition( VECTOR2I( bbox.GetCenter().x, -bbox.GetTop() ) );
737
738 ksymbol->GetValueField().SetVertJustify( GR_TEXT_V_ALIGN_TOP );
739 ksymbol->GetValueField().SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
740 ksymbol->GetValueField().SetPosition( VECTOR2I( bbox.GetCenter().x, -bbox.GetBottom() ) );*/
741
742 symInfo.libSymbol = std::move( ksymbolPtr );
743
744 return symInfo;
745}
746
747
749 const nlohmann::json& aProject,
750 std::map<wxString, EASYEDAPRO::SYM_INFO>& aSymbolMap,
751 const std::map<wxString, EASYEDAPRO::BLOB>& aBlobMap,
752 const std::vector<nlohmann::json>& aLines,
753 const wxString& aLibName )
754{
755 std::vector<std::unique_ptr<SCH_ITEM>> createdItems;
756
757 std::map<wxString, std::vector<nlohmann::json>> parentedLines;
758 std::map<wxString, std::vector<nlohmann::json>> ruleLines;
759
760 std::map<wxString, nlohmann::json> lineStyles;
761 std::map<wxString, nlohmann::json> fontStyles;
762
763 for( const nlohmann::json& line : aLines )
764 {
765 wxString type = line.at( 0 );
766
767 if( type == wxS( "LINESTYLE" ) )
768 lineStyles[line.at( 1 )] = line;
769 else if( type == wxS( "FONTSTYLE" ) )
770 fontStyles[line.at( 1 )] = line;
771 }
772
773 for( const nlohmann::json& line : aLines )
774 {
775 wxString type = line.at( 0 );
776
777 if( type == wxS( "RECT" ) )
778 {
779 VECTOR2D start( line.at( 2 ), line.at( 3 ) );
780 VECTOR2D end( line.at( 4 ), line.at( 5 ) );
781 wxString styleStr = line.at( 9 );
782
783 std::unique_ptr<SCH_SHAPE> rect = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
784
785 rect->SetStart( ScalePos( start ) );
786 rect->SetEnd( ScalePos( end ) );
787
788 ApplyLineStyle( lineStyles, rect, styleStr );
789
790 createdItems.push_back( std::move( rect ) );
791 }
792 else if( type == wxS( "CIRCLE" ) )
793 {
794 VECTOR2D center( line.at( 2 ), line.at( 3 ) );
795 double radius = line.at( 4 );
796 wxString styleStr = line.at( 5 );
797
798 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
799
800 circle->SetCenter( ScalePos( center ) );
801 circle->SetEnd( circle->GetCenter() + VECTOR2I( ScaleSize( radius ), 0 ) );
802
803 ApplyLineStyle( lineStyles, circle, styleStr );
804
805 createdItems.push_back( std::move( circle ) );
806 }
807 else if( type == wxS( "POLY" ) )
808 {
809 std::vector<double> points = line.at( 2 );
810 wxString styleStr = line.at( 4 );
811
812 SHAPE_LINE_CHAIN chain;
813
814 for( size_t i = 1; i < points.size(); i += 2 )
815 chain.Append( ScalePos( VECTOR2D( points[i - 1], points[i] ) ) );
816
817 for( int segId = 0; segId < chain.SegmentCount(); segId++ )
818 {
819 const SEG& seg = chain.CSegment( segId );
820
821 std::unique_ptr<SCH_LINE> schLine =
822 std::make_unique<SCH_LINE>( seg.A, LAYER_NOTES );
823 schLine->SetEndPoint( seg.B );
824
825 ApplyLineStyle( lineStyles, schLine, styleStr );
826
827 createdItems.push_back( std::move( schLine ) );
828 }
829 }
830 else if( type == wxS( "TEXT" ) )
831 {
832 VECTOR2D pos( line.at( 2 ), line.at( 3 ) );
833 double angle = line.at( 4 );
834 wxString textStr = line.at( 5 );
835 wxString fontStyleStr = line.at( 6 );
836
837 std::unique_ptr<SCH_TEXT> text =
838 std::make_unique<SCH_TEXT>( ScalePos( pos ), UnescapeHTML( textStr ) );
839
840 text->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
841 text->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
842
843 text->SetTextAngleDegrees( angle );
844
845 ApplyFontStyle( fontStyles, text, fontStyleStr );
846
847 createdItems.push_back( std::move( text ) );
848 }
849 else if( type == wxS( "OBJ" ) )
850 {
851 VECTOR2D start, size;
852 wxString mimeType, base64Data;
853 double angle = 0;
854 int flipped = 0;
855
856 if( line.at( 3 ).is_number() )
857 {
858 start = VECTOR2D( line.at( 3 ), line.at( 4 ) );
859 size = VECTOR2D( line.at( 5 ), line.at( 6 ) );
860 angle = line.at( 7 );
861 flipped = line.at( 8 );
862
863 wxString imageUrl = line.at( 9 );
864
865 if( imageUrl.BeforeFirst( ':' ) == wxS( "data" ) )
866 {
867 wxArrayString paramsArr =
868 wxSplit( imageUrl.AfterFirst( ':' ).BeforeFirst( ',' ), ';', '\0' );
869
870 base64Data = imageUrl.AfterFirst( ',' );
871
872 if( paramsArr.size() > 0 )
873 mimeType = paramsArr[0];
874 }
875 else if( imageUrl.BeforeFirst( ':' ) == wxS( "blob" ) )
876 {
877 wxString objectId = imageUrl.AfterLast( ':' );
878
879 if( auto blob = get_opt( aBlobMap, objectId ) )
880 {
881 wxString blobUrl = blob->url;
882
883 if( blobUrl.BeforeFirst( ':' ) == wxS( "data" ) )
884 {
885 wxArrayString paramsArr = wxSplit(
886 blobUrl.AfterFirst( ':' ).BeforeFirst( ',' ), ';', '\0' );
887
888 base64Data = blobUrl.AfterFirst( ',' );
889
890 if( paramsArr.size() > 0 )
891 mimeType = paramsArr[0];
892 }
893 }
894 }
895 }
896 else if( line.at( 3 ).is_string() )
897 {
898 mimeType = line.at( 3 ).get<wxString>().BeforeFirst( ';' );
899
900 start = VECTOR2D( line.at( 4 ), line.at( 5 ) );
901 size = VECTOR2D( line.at( 6 ), line.at( 7 ) );
902 angle = line.at( 8 );
903 base64Data = line.at( 9 ).get<wxString>();
904 }
905
906 VECTOR2D kstart = ScalePos( start );
907 VECTOR2D ksize = ScaleSize( size );
908
909 if( mimeType.empty() || base64Data.empty() )
910 continue;
911
912 wxMemoryBuffer buf = wxBase64Decode( base64Data );
913
914 if( mimeType == wxS( "image/svg+xml" ) )
915 {
916 SVG_IMPORT_PLUGIN svgImportPlugin;
917 GRAPHICS_IMPORTER_SCH schImporter;
918
919 svgImportPlugin.SetImporter( &schImporter );
920 svgImportPlugin.LoadFromMemory( buf );
921
922 VECTOR2D imSize( svgImportPlugin.GetImageWidth(),
923 svgImportPlugin.GetImageHeight() );
924
925 VECTOR2D pixelScale( schIUScale.IUTomm( ScaleSize( size.x ) ) / imSize.x,
926 schIUScale.IUTomm( ScaleSize( size.y ) ) / imSize.y );
927
928 schImporter.SetScale( pixelScale );
929
930 VECTOR2D offsetMM( schIUScale.IUTomm( kstart.x ), schIUScale.IUTomm( kstart.y ) );
931
932 schImporter.SetImportOffsetMM( offsetMM );
933
934 svgImportPlugin.Import();
935
936 for( std::unique_ptr<EDA_ITEM>& item : schImporter.GetItems() )
937 {
938 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item.release() );
939
940 for( double i = angle; i > 0; i -= 90 )
941 {
942 if( schItem->Type() == SCH_LINE_T )
943 {
944 // Lines need special handling for some reason
945 schItem->SetFlags( STARTPOINT );
946 schItem->Rotate( kstart );
947 schItem->ClearFlags( STARTPOINT );
948
949 schItem->SetFlags( ENDPOINT );
950 schItem->Rotate( kstart );
951 schItem->ClearFlags( ENDPOINT );
952 }
953 else
954 {
955 schItem->Rotate( kstart );
956 }
957 }
958
959 if( flipped )
960 {
961 // Lines need special handling for some reason
962 if( schItem->Type() == SCH_LINE_T )
963 schItem->SetFlags( STARTPOINT | ENDPOINT );
964
965 schItem->MirrorHorizontally( kstart.x );
966
967 if( schItem->Type() == SCH_LINE_T )
968 schItem->ClearFlags( STARTPOINT | ENDPOINT );
969 }
970
971 createdItems.emplace_back( schItem );
972 }
973 }
974 else
975 {
976 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
977
978 wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
979 & ~wxImage::Load_Verbose );
980
981 if( bitmap->ReadImageFile( buf ) )
982 {
983 VECTOR2D kcenter = kstart + ksize / 2;
984
985 double scaleFactor = ScaleSize( size.x ) / bitmap->GetSize().x;
986 bitmap->SetImageScale( scaleFactor );
987 bitmap->SetPosition( kcenter );
988
989 for( double i = angle; i > 0; i -= 90 )
990 bitmap->Rotate( kstart );
991
992 if( flipped )
993 bitmap->MirrorHorizontally( kstart.x );
994
995 createdItems.push_back( std::move( bitmap ) );
996 }
997 }
998 }
999 if( type == wxS( "WIRE" ) )
1000 {
1001 wxString wireId = line.at( 1 );
1002 parentedLines[wireId].push_back( line );
1003 }
1004 else if( type == wxS( "COMPONENT" ) )
1005 {
1006 wxString compId = line.at( 1 );
1007 parentedLines[compId].push_back( line );
1008 }
1009 else if( type == wxS( "ATTR" ) )
1010 {
1011 wxString compId = line.at( 2 );
1012 parentedLines[compId].push_back( line );
1013 }
1014 }
1015
1016 for( auto& [parentId, lines] : parentedLines )
1017 {
1018 std::optional<EASYEDAPRO::SCH_COMPONENT> component;
1019 std::optional<EASYEDAPRO::SCH_WIRE> wire;
1020 std::map<wxString, EASYEDAPRO::SCH_ATTR> attributes;
1021
1022 for( const nlohmann::json& line : lines )
1023 {
1024 if( line.at( 0 ) == "COMPONENT" )
1025 {
1026 component = line;
1027 }
1028 else if( line.at( 0 ) == "WIRE" )
1029 {
1030 wire = line;
1031 }
1032 else if( line.at( 0 ) == "ATTR" )
1033 {
1034 EASYEDAPRO::SCH_ATTR attr = line;
1035 attributes.emplace( attr.key, attr );
1036 }
1037 }
1038
1039 if( component )
1040 {
1041 auto deviceAttr = get_opt( attributes, "Device" );
1042 auto symbolAttr = get_opt( attributes, "Symbol" );
1043
1044 if( !deviceAttr )
1045 continue;
1046
1047 nlohmann::json compAttrs =
1048 aProject.at( "devices" ).at( deviceAttr->value ).at( "attributes" );
1049
1050 wxString symbolId;
1051
1052 if( symbolAttr && !symbolAttr->value.IsEmpty() )
1053 symbolId = symbolAttr->value;
1054 else
1055 symbolId = compAttrs.at( "Symbol" ).get<wxString>();
1056
1057 auto it = aSymbolMap.find( symbolId );
1058 if( it == aSymbolMap.end() )
1059 {
1060 wxLogError( "Symbol of '%s' with uuid '%s' not found.", component->name, symbolId );
1061 continue;
1062 }
1063
1064 EASYEDAPRO::SYM_INFO& esymInfo = it->second;
1065 LIB_SYMBOL newLibSymbol = *esymInfo.libSymbol.get();
1066
1067 wxString unitName = component->name;
1068
1069 LIB_ID libId =
1070 EASYEDAPRO::ToKiCadLibID( aLibName, newLibSymbol.GetLibId().GetLibItemName() );
1071
1072 std::unique_ptr<SCH_SYMBOL> schSym =
1073 std::make_unique<SCH_SYMBOL>( newLibSymbol, libId, &aSchematic->CurrentSheet(),
1074 esymInfo.partUnits[unitName] );
1075
1076 schSym->SetFootprintFieldText( newLibSymbol.GetFootprintField().GetText() );
1077
1078 for( double i = component->rotation; i > 0; i -= 90 )
1079 schSym->Rotate( VECTOR2I() );
1080
1081 if( component->mirror )
1082 schSym->MirrorHorizontally( 0 );
1083
1084 schSym->SetPosition( ScalePos( component->position ) );
1085
1087 {
1088 if( auto globalNetAttr = get_opt( attributes, "Global Net Name" ) )
1089 {
1090 ApplyAttrToField( fontStyles, schSym->GetField( VALUE_FIELD ), *globalNetAttr,
1091 false, true, schSym.get() );
1092
1093 for( LIB_PIN* pin : schSym->GetAllLibPins() )
1094 pin->SetName( globalNetAttr->value );
1095 }
1096 else
1097 {
1098 schSym->GetField( VALUE_FIELD )
1099 ->SetText( newLibSymbol.GetValueField().GetText() );
1100 }
1101
1102 schSym->SetRef( &aSchematic->CurrentSheet(), wxS( "#PWR?" ) );
1103 schSym->GetField( REFERENCE_FIELD )->SetVisible( false );
1104 }
1105 else if( esymInfo.head.symbolType == EASYEDAPRO::SYMBOL_TYPE::NETPORT )
1106 {
1107 auto nameAttr = get_opt( attributes, "Name" );
1108
1109 if( nameAttr )
1110 {
1111 std::unique_ptr<SCH_GLOBALLABEL> label = std::make_unique<SCH_GLOBALLABEL>(
1112 ScalePos( component->position ), nameAttr->value );
1113
1115
1116 for( double i = component->rotation; i > 0; i -= 90 )
1117 spin = spin.RotateCCW();
1118
1119 label->SetSpinStyle( spin );
1120
1121 if( esymInfo.symbolAttr )
1122 {
1123 wxString symStr = esymInfo.symbolAttr->value;
1124
1125 if( symStr == wxS( "Netport-IN" ) )
1126 label->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
1127 if( symStr == wxS( "Netport-OUT" ) )
1128 label->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
1129 if( symStr == wxS( "Netport-BI" ) )
1130 label->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
1131 }
1132
1133 nlohmann::json style = fontStyles[nameAttr->fontStyle];
1134
1135 if( !style.is_null() && style.at( 5 ).is_number() )
1136 {
1137 double size = style.at( 5 ).get<double>() * 0.5;
1138 label->SetTextSize( VECTOR2I( ScaleSize( size ), ScaleSize( size ) ) );
1139 }
1140
1141 createdItems.push_back( std::move( label ) );
1142 }
1143
1144 continue;
1145 }
1146 else
1147 {
1148 auto nameAttr = get_opt( attributes, "Name" );
1149 auto valueAttr = get_opt( attributes, "Value" );
1150
1151 std::optional<EASYEDAPRO::SCH_ATTR> targetValueAttr;
1152
1153 if( valueAttr && !valueAttr->value.empty() && valueAttr->valVisible )
1154 targetValueAttr = valueAttr;
1155 else if( nameAttr && !nameAttr->value.empty() && nameAttr->valVisible )
1156 targetValueAttr = nameAttr;
1157 else if( valueAttr && !valueAttr->value.empty() )
1158 targetValueAttr = valueAttr;
1159 else if( nameAttr && !nameAttr->value.empty() )
1160 targetValueAttr = nameAttr;
1161
1162 if( targetValueAttr )
1163 ApplyAttrToField( fontStyles, schSym->GetField( VALUE_FIELD ), *targetValueAttr,
1164 false, true, schSym.get() );
1165
1166 if( auto descrAttr = get_opt( attributes, "Description" ) )
1167 ApplyAttrToField( fontStyles, schSym->GetField( DESCRIPTION_FIELD ), *descrAttr,
1168 false, true, schSym.get() );
1169
1170 if( auto designatorAttr = get_opt( attributes, "Designator" ) )
1171 {
1172 ApplyAttrToField( fontStyles, schSym->GetField( REFERENCE_FIELD ),
1173 *designatorAttr, false, true, schSym.get() );
1174
1175 schSym->SetRef( &aSchematic->CurrentSheet(), designatorAttr->value );
1176 }
1177
1178 for( auto& [attrKey, attr] : attributes )
1179 {
1180 if( attrKey == wxS( "Name" ) || attrKey == wxS( "Value" )
1181 || attrKey == wxS( "Global Net Name" ) || attrKey == wxS( "Designator" )
1182 || attrKey == wxS( "Description" ) || attrKey == wxS( "Device" )
1183 || attrKey == wxS( "Footprint" ) || attrKey == wxS( "Symbol" )
1184 || attrKey == wxS( "Unique ID" ) )
1185 {
1186 continue;
1187 }
1188
1189 if( attr.value.IsEmpty() )
1190 continue;
1191
1192 SCH_FIELD* text =
1193 new SCH_FIELD( schSym.get(), schSym->GetFieldCount(), attrKey );
1194
1195 text->SetPosition( schSym->GetPosition() );
1196
1197 ApplyAttrToField( fontStyles, text, attr, false, true, schSym.get() );
1198 schSym->AddField( *text );
1199 }
1200 }
1201
1202 for( const EASYEDAPRO::PIN_INFO& pinInfo : esymInfo.pins )
1203 {
1204 wxString pinKey = parentId + pinInfo.pin.id;
1205 auto pinLines = get_opt( parentedLines, pinKey );
1206
1207 if( !pinLines )
1208 continue;
1209
1210 for( const nlohmann::json& pinLine : *pinLines )
1211 {
1212 if( pinLine.at( 0 ) != "ATTR" )
1213 continue;
1214
1215 EASYEDAPRO::SCH_ATTR attr = pinLine;
1216
1217 if( attr.key != wxS( "NO_CONNECT" ) )
1218 continue;
1219
1220 if( SCH_PIN* schPin = schSym->GetPin( pinInfo.number ) )
1221 {
1222 VECTOR2I pos = schSym->GetPinPhysicalPosition( schPin->GetLibPin() );
1223
1224 std::unique_ptr<SCH_NO_CONNECT> noConn =
1225 std::make_unique<SCH_NO_CONNECT>( pos );
1226
1227 createdItems.push_back( std::move( noConn ) );
1228 }
1229 }
1230 }
1231
1232 createdItems.push_back( std::move( schSym ) );
1233 }
1234 else // Not component
1235 {
1236 std::vector<SHAPE_LINE_CHAIN> wireLines;
1237
1238 if( wire )
1239 {
1240 for( const std::vector<double>& ptArr : wire->geometry )
1241 {
1242 SHAPE_LINE_CHAIN chain;
1243
1244 for( size_t i = 1; i < ptArr.size(); i += 2 )
1245 chain.Append( ScalePos( VECTOR2D( ptArr[i - 1], ptArr[i] ) ) );
1246
1247 if( chain.PointCount() < 2 )
1248 continue;
1249
1250 wireLines.push_back( chain );
1251
1252 for( int segId = 0; segId < chain.SegmentCount(); segId++ )
1253 {
1254 const SEG& seg = chain.CSegment( segId );
1255
1256 std::unique_ptr<SCH_LINE> schLine =
1257 std::make_unique<SCH_LINE>( seg.A, LAYER_WIRE );
1258 schLine->SetEndPoint( seg.B );
1259
1260 createdItems.push_back( std::move( schLine ) );
1261 }
1262 }
1263 }
1264
1265 auto netAttr = get_opt( attributes, "NET" );
1266
1267 if( netAttr )
1268 {
1269 if( !netAttr->valVisible )
1270 continue;
1271
1272 VECTOR2I kpos = ScalePos( *netAttr->position );
1273 VECTOR2I nearestPos = kpos;
1274 SEG::ecoord min_dist_sq = VECTOR2I::ECOORD_MAX;
1275
1276 for( const SHAPE_LINE_CHAIN& chain : wireLines )
1277 {
1278 VECTOR2I nearestPt = chain.NearestPoint( kpos, false );
1279 SEG::ecoord dist_sq = ( nearestPt - kpos ).SquaredEuclideanNorm();
1280
1281 if( dist_sq < min_dist_sq )
1282 {
1283 min_dist_sq = dist_sq;
1284 nearestPos = nearestPt;
1285 }
1286 }
1287
1288 std::unique_ptr<SCH_LABEL> label = std::make_unique<SCH_LABEL>();
1289
1290 label->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1291 label->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM );
1292
1293 for( double i = netAttr->rotation; i > 0; i -= 90 )
1294 label->Rotate90( true );
1295
1296 label->SetPosition( nearestPos );
1297 label->SetText( netAttr->value );
1298
1299 ApplyFontStyle( fontStyles, label, netAttr->fontStyle );
1300
1301 createdItems.push_back( std::move( label ) );
1302 }
1303 }
1304 }
1305
1306 // Adjust page to content
1307 BOX2I sheetBBox;
1308
1309 for( std::unique_ptr<SCH_ITEM>& ptr : createdItems )
1310 {
1311 if( ptr->Type() == SCH_SYMBOL_T )
1312 sheetBBox.Merge( static_cast<SCH_SYMBOL*>( ptr.get() )->GetBodyAndPinsBoundingBox() );
1313 else
1314 sheetBBox.Merge( ptr->GetBoundingBox() );
1315 }
1316
1317 SCH_SCREEN* screen = aRootSheet->GetScreen();
1318 PAGE_INFO pageInfo = screen->GetPageSettings();
1319
1320 int alignGrid = schIUScale.MilsToIU( 50 );
1321
1322 VECTOR2D offset( -sheetBBox.GetLeft(), -sheetBBox.GetTop() );
1323 offset.x = KiROUND( offset.x / alignGrid ) * alignGrid;
1324 offset.y = KiROUND( offset.y / alignGrid ) * alignGrid;
1325
1326 pageInfo.SetWidthMils( schIUScale.IUToMils( sheetBBox.GetWidth() ) );
1327 pageInfo.SetHeightMils( schIUScale.IUToMils( sheetBBox.GetHeight() ) );
1328
1329 screen->SetPageSettings( pageInfo );
1330
1331 for( std::unique_ptr<SCH_ITEM>& ptr : createdItems )
1332 {
1333 ptr->Move( offset );
1334 screen->Append( ptr.release() );
1335 }
1336}
int color
Definition: DXF_plotter.cpp:58
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
coord_type GetTop() const
Definition: box2.h:195
coord_type GetHeight() const
Definition: box2.h:189
coord_type GetWidth() const
Definition: box2.h:188
coord_type GetLeft() const
Definition: box2.h:194
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:589
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:123
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:125
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:95
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:229
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:183
void SetImportOffsetMM(const VECTOR2D &aOffset)
Set the offset in millimeters to add to coordinates when importing graphic items.
void SetScale(const VECTOR2D &aScale)
Set the scale factor affecting the imported shapes.
std::list< std::unique_ptr< EDA_ITEM > > & GetItems()
Return the list of objects representing the imported shapes.
virtual void SetImporter(GRAPHICS_IMPORTER *aImporter)
Set the receiver of the imported shapes.
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
Definition: font.cpp:146
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:68
Define a library symbol object.
Definition: lib_symbol.h:99
void SetShowPinNames(bool aShow)
Set or clear the pin name visibility flag.
Definition: lib_symbol.h:632
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
void SetUnitCount(int aCount, bool aDuplicateDrawItems=true)
Set the units per symbol count.
void SetPower()
Definition: lib_symbol.cpp:718
LIB_FIELD & GetFootprintField()
Return reference to the footprint field.
void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition: lib_symbol.h:640
LIB_ID GetLibId() const override
Definition: lib_symbol.h:163
wxString GetName() const override
Definition: lib_symbol.h:160
void SetDescription(const wxString &aDescription)
Gets the Description field text value *‍/.
Definition: lib_symbol.h:172
void SetKeyWords(const wxString &aKeyWords)
Definition: lib_symbol.h:189
void AddDrawItem(LIB_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
LIB_FIELD & GetValueField()
Return reference to the value field.
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:58
void SetHeightMils(double aHeightInMils)
Definition: page_info.cpp:261
void SetWidthMils(double aWidthInMils)
Definition: page_info.cpp:247
A progress reporter interface for use in multi-threaded environments.
Holds all the data relating to one schematic.
Definition: schematic.h:75
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:136
static double Convert(wxString aValue)
static VECTOR2< T > ScalePos(VECTOR2< T > aValue)
double SizeToKi(wxString units)
static T ScaleSize(T aValue)
void ApplyFontStyle(const std::map< wxString, nlohmann::json > &fontStyles, T &text, const wxString &styleStr)
EASYEDAPRO::SYM_INFO ParseSymbol(const std::vector< nlohmann::json > &aLines)
static VECTOR2< T > ScalePosSym(VECTOR2< T > aValue)
SCH_EASYEDAPRO_PARSER(SCHEMATIC *aSchematic, PROGRESS_REPORTER *aProgressReporter)
void ParseSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const nlohmann::json &aProject, std::map< wxString, EASYEDAPRO::SYM_INFO > &aSymbolMap, const std::map< wxString, EASYEDAPRO::BLOB > &aBlobMap, const std::vector< nlohmann::json > &aLines, const wxString &aLibName)
void ApplyAttrToField(const std::map< wxString, nlohmann::json > &fontStyles, T *text, const EASYEDAPRO::SCH_ATTR &aAttr, bool aIsSym, bool aToSym, SCH_SYMBOL *aParent=nullptr)
void ApplyLineStyle(const std::map< wxString, nlohmann::json > &lineStyles, T &shape, const wxString &styleStr)
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:52
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:151
virtual void MirrorHorizontally(int aCenter)=0
Mirror item horizontally about aCenter.
virtual void Rotate(const VECTOR2I &aCenter)=0
Rotate the item around aCenter 90 degrees in the clockwise direction.
const PAGE_INFO & GetPageSettings() const
Definition: sch_screen.h:131
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:149
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: sch_screen.h:132
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:110
Schematic symbol object.
Definition: sch_symbol.h:81
BOX2I GetBodyAndPinsBoundingBox() const
Return a bounding box for the symbol body and pins but not the fields.
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I::extended_type ecoord
Definition: seg.h:44
VECTOR2I B
Definition: seg.h:50
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
SPIN_STYLE RotateCCW()
Definition: sch_label.cpp:156
Simple container to manage line stroke parameters.
Definition: stroke_params.h:81
void SetLineStyle(LINE_STYLE aLineStyle)
Definition: stroke_params.h:95
void SetWidth(int aWidth)
Definition: stroke_params.h:92
void SetColor(const KIGFX::COLOR4D &aColor)
Definition: stroke_params.h:98
bool Import() override
Actually imports the file.
virtual double GetImageWidth() const override
Return image width from original imported file.
bool LoadFromMemory(const wxMemoryBuffer &aMemBuffer) override
Set memory buffer with content for import.
virtual double GetImageHeight() const override
Return image height from original imported file.
static constexpr extended_type ECOORD_MAX
Definition: vector2d.h:75
#define _(s)
static constexpr EDA_ANGLE & ANGLE_HORIZONTAL
Definition: eda_angle.h:433
static constexpr EDA_ANGLE & ANGLE_VERTICAL
Definition: eda_angle.h:434
#define ENDPOINT
ends. (Used to support dragging.)
#define STARTPOINT
When a line is selected, these flags indicate which.
void ConvertImageToLibShapes(LIB_SYMBOL *aSymbol, int unit, wxImage img, VECTOR2D pixelScale, VECTOR2D offset)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
@ LAYER_WIRE
Definition: layer_ids.h:349
@ LAYER_NOTES
Definition: layer_ids.h:363
std::optional< V > get_opt(const std::map< wxString, V > &aMap, const wxString &aKey)
Definition: map_helpers.h:34
LIB_ID ToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
PIN_ORIENTATION
The symbol library pin object orientations.
Definition: pin_type.h:75
static LINE_STYLE ConvertStrokeStyle(const wxString &aStyle)
static LINE_STYLE ConvertStrokeStyle(int aStyle)
@ SYM_ORIENT_270
@ SYM_MIRROR_Y
@ SYM_ORIENT_180
@ SYM_MIRROR_X
@ SYM_ORIENT_90
@ SYM_ORIENT_0
const int scale
wxString UnescapeHTML(const wxString &aString)
Return a new wxString unescaped from HTML format.
LINE_STYLE
Dashed line types.
Definition: stroke_params.h:48
EASYEDAPRO::SYM_PIN pin
std::optional< VECTOR2D > position
std::unique_ptr< LIB_SYMBOL > libSymbol
std::vector< PIN_INFO > pins
std::optional< EASYEDAPRO::SCH_ATTR > symbolAttr
std::map< wxString, int > partUnits
EASYEDAPRO::SYM_HEAD head
constexpr double IUTomm(int iu) const
Definition: base_units.h:87
constexpr int IUToMils(int iu) const
Definition: base_units.h:100
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
@ DESCRIPTION_FIELD
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
GR_TEXT_H_ALIGN_T
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
GR_TEXT_V_ALIGN_T
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
Definition: trigo.cpp:520
@ SCH_LINE_T
Definition: typeinfo.h:146
@ SCH_SYMBOL_T
Definition: typeinfo.h:156
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< double > VECTOR2D
Definition: vector2d.h:587
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588