KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_easyeda_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 The 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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <font/font.h>
22#include "sch_easyeda_parser.h"
23
24#include <sch_io/sch_io_mgr.h>
25#include <schematic.h>
26#include <sch_sheet.h>
27#include <sch_line.h>
28#include <sch_no_connect.h>
29#include <sch_label.h>
30#include <sch_junction.h>
31#include <sch_edit_frame.h>
32#include <sch_shape.h>
33#include <sch_bitmap.h>
34#include <string_utils.h>
35#include <bezier_curves.h>
36#include <wx/base64.h>
37#include <wx/mstream.h>
38#include <core/map_helpers.h>
39#include <gfx_import_utils.h>
43
44
45// clang-format off
46static const std::vector<wxString> c_attributesWhitelist = { "Datasheet",
47 "Manufacturer Part",
48 "Manufacturer",
49 "BOM_Manufacturer Part",
50 "BOM_Manufacturer",
51 "Supplier Part",
52 "Supplier",
53 "BOM_Supplier Part",
54 "BOM_Supplier",
55 "LCSC Part Name" };
56// clang-format on
57
58
60 PROGRESS_REPORTER* aProgressReporter )
61{
62 m_schematic = aSchematic;
63}
64
65
69
70
71static std::vector<std::vector<wxString>> RegexMatchAll( wxRegEx& aRegex, const wxString& aString )
72{
73 std::vector<std::vector<wxString>> allMatches;
74
75 size_t start = 0;
76 size_t len = 0;
77 size_t prevstart = 0;
78
79 wxString str = aString;
80
81 while( aRegex.Matches( str ) )
82 {
83 std::vector<wxString> matches;
84 aRegex.GetMatch( &start, &len );
85
86 for( size_t i = 0; i < aRegex.GetMatchCount(); i++ )
87 matches.emplace_back( aRegex.GetMatch( str, i ) );
88
89 allMatches.emplace_back( matches );
90
91 prevstart = start + len;
92 str = str.Mid( prevstart );
93 }
94
95 return allMatches;
96}
97
98
106static std::vector<std::pair<wxString, std::vector<double>>>
107ParseImageTransform( const wxString& transformData )
108{
109 wxRegEx transformRegex( "(rotate|translate|scale)\\(([\\w\\s,\\.\\-]*)\\)", wxRE_ICASE );
110 std::vector<std::vector<wxString>> allMatches = RegexMatchAll( transformRegex, transformData );
111
112 std::vector<std::pair<wxString, std::vector<double>>> transformCmds;
113
114 for( int cmdId = allMatches.size() - 1; cmdId >= 0; cmdId-- )
115 {
116 std::vector<wxString>& groups = allMatches[cmdId];
117
118 if( groups.size() != 3 )
119 continue;
120
121 const wxString& cmdName = groups[1].Strip( wxString::both ).Lower();
122 const wxString& cmdArgsStr = groups[2];
123
124 wxArrayString cmdParts = wxSplit( cmdArgsStr, ',', '\0' );
125 std::vector<double> cmdArgs;
126
127 for( const wxString& cmdPart : cmdParts )
128 {
129 double arg = 0;
130 wxASSERT( cmdPart.Strip( wxString::both ).ToCDouble( &arg ) );
131
132 cmdArgs.push_back( arg );
133 }
134
135 transformCmds.emplace_back( cmdName, cmdArgs );
136 }
137
138 return transformCmds;
139}
140
141
142static LIB_ID EasyEdaToKiCadLibID( const wxString& aLibName, const wxString& aLibReference )
143{
144 wxString libReference = EscapeString( aLibReference, CTX_LIBID );
145
146 wxString key = !aLibName.empty() ? ( aLibName + ':' + libReference ) : libReference;
147
148 LIB_ID libId;
149 libId.Parse( key, true );
150
151 return libId;
152}
153
154
155static LINE_STYLE ConvertStrokeStyle( const wxString& aStyle )
156{
157 if( aStyle == wxS( "0" ) )
158 return LINE_STYLE::SOLID;
159 else if( aStyle == wxS( "1" ) )
160 return LINE_STYLE::DASH;
161 else if( aStyle == wxS( "2" ) )
162 return LINE_STYLE::DOT;
163
164 return LINE_STYLE::DEFAULT;
165}
166
167
168static ELECTRICAL_PINTYPE ConvertElecType( const wxString& aType )
169{
170 if( aType == wxS( "0" ) )
172 else if( aType == wxS( "1" ) )
174 else if( aType == wxS( "2" ) )
176 else if( aType == wxS( "3" ) )
178 else if( aType == wxS( "4" ) )
180
182}
183
184
186 REPORTER* aReporter )
187{
189 {
191 line1->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
192 line1->AddPoint( { 0, 0 } );
193 line1->AddPoint( { 0, schIUScale.MilsToIU( 50 ) } );
194 aKsymbol->AddDrawItem( line1, false );
195
197 {
199 circle->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 5 ), LINE_STYLE::SOLID ) );
200 circle->SetPosition( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( 75 ) } );
201 circle->SetEnd( circle->GetPosition() + VECTOR2I( schIUScale.MilsToIU( 25 ), 0 ) );
202 aKsymbol->AddDrawItem( circle, false );
203 }
204 else
205 {
207 line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
208 line2->AddPoint( { schIUScale.MilsToIU( -25 ), schIUScale.MilsToIU( 50 ) } );
209 line2->AddPoint( { schIUScale.MilsToIU( 25 ), schIUScale.MilsToIU( 50 ) } );
210 line2->AddPoint( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( 100 ) } );
211 line2->AddPoint( { schIUScale.MilsToIU( -25 ), schIUScale.MilsToIU( 50 ) } );
212 aKsymbol->AddDrawItem( line2, false );
213 }
214
215 return { 0, schIUScale.MilsToIU( 150 ) };
216 }
217 else if( aStyle == EASYEDA::POWER_FLAG_STYLE::WAVE )
218 {
220 line->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
221 line->AddPoint( { 0, 0 } );
222 line->AddPoint( { 0, schIUScale.MilsToIU( 72 ) } );
223 aKsymbol->AddDrawItem( line, false );
224
226 bezier->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 5 ), LINE_STYLE::SOLID ) );
227 bezier->SetStart( { schIUScale.MilsToIU( 30 ), schIUScale.MilsToIU( 50 ) } );
228 bezier->SetBezierC1( { schIUScale.MilsToIU( 30 ), schIUScale.MilsToIU( 87 ) } );
229 bezier->SetBezierC2( { schIUScale.MilsToIU( -30 ), schIUScale.MilsToIU( 63 ) } );
230 bezier->SetEnd( { schIUScale.MilsToIU( -30 ), schIUScale.MilsToIU( 100 ) } );
231 aKsymbol->AddDrawItem( bezier, false );
232
233 return { 0, schIUScale.MilsToIU( 150 ) };
234 }
239 {
241 line1->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
242 line1->AddPoint( { 0, 0 } );
243 line1->AddPoint( { 0, schIUScale.MilsToIU( 100 ) } );
244 aKsymbol->AddDrawItem( line1, false );
245
247 {
249 line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
250 line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( 100 ) } );
251 line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( 100 ) } );
252 aKsymbol->AddDrawItem( line2, false );
253
255 line3->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
256 line3->AddPoint( { schIUScale.MilsToIU( -70 ), schIUScale.MilsToIU( 120 ) } );
257 line3->AddPoint( { schIUScale.MilsToIU( 70 ), schIUScale.MilsToIU( 120 ) } );
258 aKsymbol->AddDrawItem( line3, false );
259
261 line4->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
262 line4->AddPoint( { schIUScale.MilsToIU( -40 ), schIUScale.MilsToIU( 140 ) } );
263 line4->AddPoint( { schIUScale.MilsToIU( 40 ), schIUScale.MilsToIU( 140 ) } );
264 aKsymbol->AddDrawItem( line4, false );
265
267 line5->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
268 line5->AddPoint( { schIUScale.MilsToIU( -10 ), schIUScale.MilsToIU( 160 ) } );
269 line5->AddPoint( { schIUScale.MilsToIU( 10 ), schIUScale.MilsToIU( 160 ) } );
270 aKsymbol->AddDrawItem( line5, false );
271 }
273 {
275 line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
276 line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( 100 ) } );
277 line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( 100 ) } );
278 line2->AddPoint( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( 160 ) } );
279 line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( 100 ) } );
280 aKsymbol->AddDrawItem( line2, false );
281 }
282 else if( aStyle == EASYEDA::POWER_FLAG_STYLE::EARTH )
283 {
285 line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
286 line2->AddPoint( { schIUScale.MilsToIU( -150 ), schIUScale.MilsToIU( 200 ) } );
287 line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( 100 ) } );
288 line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( 100 ) } );
289 line2->AddPoint( { schIUScale.MilsToIU( 50 ), schIUScale.MilsToIU( 200 ) } );
290 aKsymbol->AddDrawItem( line2, false );
291
293 line3->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
294 line3->AddPoint( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( 100 ) } );
295 line3->AddPoint( { schIUScale.MilsToIU( -50 ), schIUScale.MilsToIU( 200 ) } );
296 aKsymbol->AddDrawItem( line3, false );
297 }
298 else // EASYEDA::POWER_FLAG_STYLE::GOST_ARROW
299 {
301 line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
302 line2->AddPoint( { schIUScale.MilsToIU( -25 ), schIUScale.MilsToIU( 50 ) } );
303 line2->AddPoint( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( 100 ) } );
304 line2->AddPoint( { schIUScale.MilsToIU( 25 ), schIUScale.MilsToIU( 50 ) } );
305 aKsymbol->AddDrawItem( line2, false );
306
307 return { 0, schIUScale.MilsToIU( 150 ) }; // special case
308 }
309
310 return { 0, schIUScale.MilsToIU( 250 ) };
311 }
314 {
316 line1->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
317 line1->AddPoint( { 0, 0 } );
318 line1->AddPoint( { 0, schIUScale.MilsToIU( 160 ) } );
319 aKsymbol->AddDrawItem( line1, false );
320
322 line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
323 line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( 160 ) } );
324 line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( 160 ) } );
325 aKsymbol->AddDrawItem( line2, false );
326
328 line3->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
329 line3->AddPoint( { schIUScale.MilsToIU( -60 ), schIUScale.MilsToIU( 200 ) } );
330 line3->AddPoint( { schIUScale.MilsToIU( 60 ), schIUScale.MilsToIU( 200 ) } );
331 aKsymbol->AddDrawItem( line3, false );
332
334 line4->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
335 line4->AddPoint( { schIUScale.MilsToIU( -20 ), schIUScale.MilsToIU( 240 ) } );
336 line4->AddPoint( { schIUScale.MilsToIU( 20 ), schIUScale.MilsToIU( 240 ) } );
337 aKsymbol->AddDrawItem( line4, false );
338
340 return { 0, schIUScale.MilsToIU( -300 ) };
341
343 circle->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
344 circle->SetPosition( { schIUScale.MilsToIU( 0 ), schIUScale.MilsToIU( 160 ) } );
345 circle->SetEnd( circle->GetPosition() + VECTOR2I( schIUScale.MilsToIU( 120 ), 0 ) );
346 aKsymbol->AddDrawItem( circle, false );
347
348 return { 0, schIUScale.MilsToIU( 350 ) };
349 }
350 else if( aStyle == EASYEDA::POWER_FLAG_STYLE::GOST_BAR )
351 {
353 line1->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
354 line1->AddPoint( { 0, 0 } );
355 line1->AddPoint( { 0, schIUScale.MilsToIU( 200 ) } );
356 aKsymbol->AddDrawItem( line1, false );
357
359 line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
360 line2->AddPoint( { schIUScale.MilsToIU( -100 ), schIUScale.MilsToIU( 200 ) } );
361 line2->AddPoint( { schIUScale.MilsToIU( 100 ), schIUScale.MilsToIU( 200 ) } );
362 aKsymbol->AddDrawItem( line2, false );
363
364 return { 0, schIUScale.MilsToIU( 250 ) };
365 }
366 else
367 {
368 if( aStyle != EASYEDA::POWER_FLAG_STYLE::BAR )
369 {
370 aReporter->Report( _( "Power Port with unknown style imported as 'Bar' type." ),
372 }
373
375 line1->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
376 line1->AddPoint( { 0, 0 } );
377 line1->AddPoint( { 0, schIUScale.MilsToIU( 100 ) } );
378 aKsymbol->AddDrawItem( line1, false );
379
381 line2->SetStroke( STROKE_PARAMS( schIUScale.MilsToIU( 10 ), LINE_STYLE::SOLID ) );
382 line2->AddPoint( { schIUScale.MilsToIU( -50 ), schIUScale.MilsToIU( 100 ) } );
383 line2->AddPoint( { schIUScale.MilsToIU( 50 ), schIUScale.MilsToIU( 100 ) } );
384 aKsymbol->AddDrawItem( line2, false );
385
386 return { 0, schIUScale.MilsToIU( 150 ) };
387 }
388}
389
390
392 std::map<wxString, wxString> paramMap,
393 wxArrayString aShapes )
394{
395 for( wxString shapeStr : aShapes )
396 {
397 wxArrayString arr = wxSplit( shapeStr, '~', '\0' );
398
399 wxString elType = arr[0];
400 if( elType == wxS( "PL" ) || elType == wxS( "PG" ) )
401 {
402 wxArrayString ptArr = wxSplit( arr[1], ' ', '\0' );
403 wxString strokeColor = arr[2];
404 double lineWidth = Convert( arr[3] );
405 LINE_STYLE strokeStyle = ConvertStrokeStyle( arr[4] );
406 wxString fillColor = arr[5].Lower();
407 //bool locked = arr[7] != wxS( "0" );
408
410
411 for( size_t i = 1; i < ptArr.size(); i += 2 )
412 {
413 chain.Append(
414 RelPosSym( VECTOR2I( Convert( ptArr[i - 1] ), Convert( ptArr[i] ) ) ) );
415 }
416
417 auto line = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY, LAYER_DEVICE );
418
419 if( elType == wxS( "PG" ) )
420 chain.SetClosed( true );
421
422 if( chain.PointCount() < 2 )
423 continue;
424
425 for( int i = 0; i < chain.PointCount(); i++ )
426 line->AddPoint( chain.CPoint( i ) );
427
428 if( chain.IsClosed() )
429 line->AddPoint( chain.CPoint( 0 ) );
430
431 line->SetUnit( 0 );
432 line->SetStroke( STROKE_PARAMS( ScaleSize( lineWidth ), strokeStyle ) );
433
434 if( fillColor != wxS( "none" ) )
435 {
436 line->SetFilled( true );
437
438 if( fillColor == strokeColor )
439 line->SetFillMode( FILL_T::FILLED_SHAPE );
440 else
441 line->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
442 }
443
444 aSymbol->AddDrawItem( line.release() );
445 }
446 else if( elType == wxS( "PT" ) ) // Freedraw
447 {
448 wxString pointsData = arr[1];
449 wxString strokeColor = arr[2];
450 double lineWidth = Convert( arr[3] );
451 LINE_STYLE strokeStyle = ConvertStrokeStyle( arr[4] );
452 wxString fillColor = arr[5].Lower();
453 //bool locked = arr[7] != wxS( "0" );
454
455 std::vector<SHAPE_LINE_CHAIN> lineChains =
456 ParseLineChains( pointsData, schIUScale.MilsToIU( 10 ), false );
457
458 for( SHAPE_LINE_CHAIN outline : lineChains )
459 {
460 auto shape = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY, LAYER_DEVICE );
461
462 if( outline.IsClosed() )
463 outline.Append( outline.CPoint( 0 ), true );
464
465 for( const VECTOR2I& pt : outline.CPoints() )
466 shape->AddPoint( pt );
467
468 shape->SetUnit( 0 );
469 shape->SetStroke( STROKE_PARAMS( ScaleSize( lineWidth ), strokeStyle ) );
470
471 if( fillColor != wxS( "none" ) )
472 {
473 shape->SetFilled( true );
474
475 if( fillColor == strokeColor )
476 shape->SetFillMode( FILL_T::FILLED_SHAPE );
477 else
478 shape->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
479 }
480
481 aSymbol->AddDrawItem( shape.release() );
482 }
483 }
484 else if( elType == wxS( "Pimage" ) )
485 {
486 //double angle = Convert( arr[4] ); // TODO
487 VECTOR2D start( Convert( arr[6] ), Convert( arr[7] ) );
488 VECTOR2D size( Convert( arr[8] ), Convert( arr[9] ) );
489 wxString imageUrl = arr[10];
490
491 if( imageUrl.BeforeFirst( ':' ) == wxS( "data" ) )
492 {
493 wxArrayString paramsArr =
494 wxSplit( imageUrl.AfterFirst( ':' ).BeforeFirst( ',' ), ';', '\0' );
495
496 wxString data = imageUrl.AfterFirst( ',' );
497
498 if( paramsArr.size() > 0 )
499 {
500 wxString mimeType = paramsArr[0];
501 wxMemoryBuffer buf = wxBase64Decode( data );
502
503 if( mimeType == wxS( "image/svg+xml" ) )
504 {
505 VECTOR2D offset = RelPosSym( start );
506
507 SVG_IMPORT_PLUGIN svgImportPlugin;
508 GRAPHICS_IMPORTER_LIB_SYMBOL libsymImporter( aSymbol, 0 );
509
510 svgImportPlugin.SetImporter( &libsymImporter );
511 svgImportPlugin.LoadFromMemory( buf );
512
513 VECTOR2D imSize( svgImportPlugin.GetImageWidth(),
514 svgImportPlugin.GetImageHeight() );
515
516 VECTOR2D pixelScale( schIUScale.IUTomm( ScaleSize( size.x ) ) / imSize.x,
517 schIUScale.IUTomm( ScaleSize( size.y ) ) / imSize.y );
518
519 libsymImporter.SetScale( pixelScale );
520
521 VECTOR2D offsetMM( schIUScale.IUTomm( offset.x ),
522 schIUScale.IUTomm( offset.y ) );
523
524 libsymImporter.SetImportOffsetMM( offsetMM );
525
526 svgImportPlugin.Import();
527
528 for( std::unique_ptr<EDA_ITEM>& item : libsymImporter.GetItems() )
529 aSymbol->AddDrawItem( static_cast<SCH_ITEM*>( item.release() ) );
530 }
531 else
532 {
533 wxMemoryInputStream memis( buf.GetData(), buf.GetDataLen() );
534
535 wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
536 & ~wxImage::Load_Verbose );
537 wxImage img;
538 if( img.LoadFile( memis, mimeType ) )
539 {
540 int dimMul = img.GetWidth() * img.GetHeight();
541 double maxPixels = 30000;
542
543 if( dimMul > maxPixels )
544 {
545 double scale = sqrt( maxPixels / dimMul );
546 img.Rescale( img.GetWidth() * scale, img.GetHeight() * scale );
547 }
548
549 VECTOR2D pixelScale( ScaleSize( size.x ) / img.GetWidth(),
550 ScaleSize( size.y ) / img.GetHeight() );
551
552 ConvertImageToLibShapes( aSymbol, 0, img, pixelScale,
553 RelPosSym( start ) );
554 }
555 }
556 }
557 }
558 }
559 else if( elType == wxS( "A" ) )
560 {
561 wxString data = arr[1];
562 wxString strokeColor = arr[3];
563 double lineWidth = Convert( arr[4] );
564 LINE_STYLE strokeStyle = ConvertStrokeStyle( arr[5] );
565 wxString fillColor = arr[6].Lower();
566 //bool locked = arr[8] != wxS( "0" );
567
568 std::vector<SHAPE_LINE_CHAIN> chains =
569 ParseLineChains( data, schIUScale.MilsToIU( 10 ), false );
570
571 auto transform = []( VECTOR2I aVec )
572 {
573 return VECTOR2I( aVec.x, aVec.y );
574 };
575
576 for( const SHAPE_LINE_CHAIN& chain : chains )
577 {
578 for( int i = 0; i <= chain.PointCount() && i != -1; i = chain.NextShape( i ) )
579 {
580 if( chain.IsArcStart( i ) )
581 {
582 SHAPE_ARC arc = chain.Arc( chain.ArcIndex( i ) );
583
584 std::unique_ptr<SCH_SHAPE> shape =
585 std::make_unique<SCH_SHAPE>( SHAPE_T::ARC, LAYER_DEVICE );
586
587 shape->SetArcGeometry( transform( arc.GetP0() ),
588 transform( arc.GetArcMid() ),
589 transform( arc.GetP1() ) );
590
591 shape->SetUnit( 0 );
592 shape->SetStroke( STROKE_PARAMS( ScaleSize( lineWidth ), strokeStyle ) );
593
594 if( fillColor != wxS( "none" ) )
595 {
596 shape->SetFilled( true );
597
598 if( fillColor == strokeColor )
599 shape->SetFillMode( FILL_T::FILLED_SHAPE );
600 else
601 shape->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
602 }
603
604 aSymbol->AddDrawItem( shape.release() );
605 }
606 else
607 {
608 SEG seg = chain.CSegment( i );
609
610 std::unique_ptr<SCH_SHAPE> shape =
611 std::make_unique<SCH_SHAPE>( SHAPE_T::POLY, LAYER_DEVICE );
612
613 shape->AddPoint( transform( seg.A ) );
614 shape->AddPoint( transform( seg.B ) );
615
616 shape->SetUnit( 0 );
617 shape->SetStroke( STROKE_PARAMS( ScaleSize( lineWidth ), strokeStyle ) );
618
619 aSymbol->AddDrawItem( shape.release() );
620 }
621 }
622 }
623 }
624 else if( elType == wxS( "R" ) )
625 {
626 VECTOR2D start( Convert( arr[1] ), Convert( arr[2] ) );
627
628 VECTOR2D cr;
629 cr.x = !arr[3].empty() ? Convert( arr[3] ) : 0,
630 cr.y = !arr[4].empty() ? Convert( arr[4] ) : 0; // TODO: corner radius
631
632 VECTOR2D size( Convert( arr[5] ), Convert( arr[6] ) );
633 wxString strokeColor = arr[7];
634 double lineWidth = Convert( arr[8] );
635 LINE_STYLE strokeStyle = ConvertStrokeStyle( arr[9] );
636 wxString fillColor = arr[10].Lower();
637 //bool locked = arr[12] != wxS( "0" );
638
639 //if( cr.x == 0 )
640 {
641 auto rect = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE, LAYER_DEVICE );
642
643 rect->SetStart( RelPosSym( start ) );
644 rect->SetEnd( RelPosSym( start + size ) );
645
646 rect->SetUnit( 0 );
647 rect->SetStroke( STROKE_PARAMS( ScaleSize( lineWidth ), strokeStyle ) );
648
649 if( fillColor != wxS( "none" ) )
650 {
651 rect->SetFilled( true );
652
653 if( fillColor == strokeColor )
654 rect->SetFillMode( FILL_T::FILLED_SHAPE );
655 else
656 rect->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
657 }
658
659 aSymbol->AddDrawItem( rect.release() );
660 }
661 // TODO: rounded rectangles
662 }
663 else if( elType == wxS( "E" ) )
664 {
665 auto circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE, LAYER_DEVICE );
666
667 VECTOR2D center( Convert( arr[1] ), Convert( arr[2] ) );
668 VECTOR2D radius( Convert( arr[3] ), Convert( arr[4] ) ); // TODO: corner radius
669 wxString strokeColor = arr[5];
670 double lineWidth = Convert( arr[6] );
671 LINE_STYLE strokeStyle = ConvertStrokeStyle( arr[7] );
672 wxString fillColor = arr[8].Lower();
673 //bool locked = arr[10] != wxS( "0" );
674
675 circle->SetCenter( RelPosSym( center ) );
676 circle->SetEnd( RelPosSym( center + VECTOR2I( radius.x, 0 ) ) );
677
678 circle->SetUnit( 0 );
679 circle->SetStroke( STROKE_PARAMS( ScaleSize( lineWidth ), strokeStyle ) );
680
681 if( fillColor != wxS( "none" ) )
682 {
683 circle->SetFilled( true );
684
685 if( fillColor == strokeColor )
686 circle->SetFillMode( FILL_T::FILLED_SHAPE );
687 else
689 }
690
691 aSymbol->AddDrawItem( circle.release() );
692 }
693 else if( elType == wxS( "P" ) )
694 {
695 wxString sepShapeStr = shapeStr;
696 sepShapeStr.Replace( wxS( "^^" ), wxS( "\n" ) );
697
698 wxArrayString segments = wxSplit( sepShapeStr, '\n', '\0' );
699 wxArrayString mainParts = wxSplit( segments[0], '~', '\0' );
700 wxArrayString pinDotParts = wxSplit( segments[1], '~', '\0' );
701 wxArrayString pinPathColorParts = wxSplit( segments[2], '~', '\0' );
702 wxArrayString pinNameParts = wxSplit( segments[3], '~', '\0' );
703 wxArrayString pinNumParts = wxSplit( segments[4], '~', '\0' );
704
705 //bool show = mainParts[1].Lower() != wxS( "none" );
706 ELECTRICAL_PINTYPE elecType = ConvertElecType( mainParts[2] );
707 wxString pinNumber = mainParts[3];
708 VECTOR2D pinPos( Convert( mainParts[4] ), Convert( mainParts[5] ) );
709 //int pinRot = Convert( mainParts[6] );
710
711 VECTOR2D pinDotPos( Convert( pinDotParts[0] ), Convert( pinDotParts[1] ) );
712
713 bool nameVisible = pinNameParts[0] != wxS( "0" );
714 wxString pinName = pinNameParts[4];
715
716 bool numVisible = pinNumParts[0] != wxS( "0" );
717 // wxString ptSize = pinNumParts[4];
718
719 VECTOR2D startPoint;
720 bool vertical = false;
721 double pinLen = 0;
722
723 // M360,290h10 or M 420 300 h -5
724 wxString lineData = pinPathColorParts[0];
725 wxRegEx regex( wxS( "^M\\s*([-\\d.]+)[,\\s]([-\\d.]+)\\s*([h|v])\\s*([-\\d.]+)\\s*$" ) );
726
727 if( regex.Matches( lineData ) )
728 {
729 startPoint.x = Convert( regex.GetMatch( lineData, 1 ) );
730 startPoint.y = Convert( regex.GetMatch( lineData, 2 ) );
731
732 vertical = regex.GetMatch( lineData, 3 ).Contains( wxS( "v" ) );
733 pinLen = Convert( regex.GetMatch( lineData, 4 ) );
734 }
735
736 int pinRotation = 0;
737
738 if( !vertical )
739 {
740 if( startPoint.x == pinPos.x && pinLen < 0 )
741 pinRotation = 180;
742 else if( startPoint.x == pinPos.x && pinLen > 0 )
743 pinRotation = 0;
744 else if( startPoint.x != pinPos.x && pinLen < 0 )
745 pinRotation = 0;
746 else if( startPoint.x != pinPos.x && pinLen > 0 )
747 pinRotation = 180;
748 }
749 else
750 {
751 if( startPoint.y == pinPos.y && pinLen < 0 )
752 pinRotation = 90;
753 else if( startPoint.y == pinPos.y && pinLen > 0 )
754 pinRotation = 270;
755 else if( startPoint.y != pinPos.y && pinLen < 0 )
756 pinRotation = 270;
757 else if( startPoint.y != pinPos.y && pinLen > 0 )
758 pinRotation = 90;
759 }
760
762
763 if( pinRotation == 0 )
765 else if( pinRotation == 90 )
767 else if( pinRotation == 180 )
769 else if( pinRotation == 270 )
771
772 int pinUnit = 0;
773 int kPinLen = ScaleSize( std::abs( pinLen ) );
774
775 if( segments.size() > 5 )
776 {
777 wxArrayString dotParts = wxSplit( segments[5], '~', '\0' );
778 wxArrayString clockParts = wxSplit( segments[6], '~', '\0' );
779
780 if( dotParts.size() == 3 && clockParts.size() == 2 )
781 {
782 if( dotParts[0] == wxS( "1" ) )
783 {
784 VECTOR2D dotPos( Convert( dotParts[1] ), Convert( dotParts[2] ) );
785
786 auto circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE, LAYER_DEVICE );
787
788 circle->SetCenter( RelPosSym( dotPos ) );
789 circle->SetEnd( RelPosSym(
790 pinPos + ( dotPos - pinPos ).Resize( std::abs( pinLen ) ) ) );
791
792 circle->SetUnit( 0 );
793
794 aSymbol->AddDrawItem( circle.release() );
795 }
796
797 if( clockParts[0] == wxS( "1" ) )
798 {
799 std::vector<SHAPE_LINE_CHAIN> lineChains =
800 ParseLineChains( clockParts[1], schIUScale.MilsToIU( 10 ), false );
801
802 for( SHAPE_LINE_CHAIN outline : lineChains )
803 {
804 auto shape = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY, LAYER_DEVICE );
805
806 if( outline.IsClosed() )
807 outline.Append( outline.CPoint( 0 ), true );
808
809 for( const VECTOR2I& pt : outline.CPoints() )
810 shape->AddPoint( pt );
811
812 shape->SetUnit( 0 );
813
814 aSymbol->AddDrawItem( shape.release() );
815 }
816 }
817 }
818 }
819
820 std::unique_ptr<SCH_PIN> pin = std::make_unique<SCH_PIN>( aSymbol );
821
822 pin->SetName( pinName );
823 pin->SetNumber( pinNumber );
824 pin->SetOrientation( orient );
825 pin->SetType( elecType );
826 pin->SetLength( kPinLen );
827 pin->SetPosition( RelPosSym( pinPos ) );
828 pin->SetUnit( pinUnit );
829
830 if( pin->GetNumberTextSize() * int( pinNumber.size() ) > kPinLen )
831 pin->SetNumberTextSize( kPinLen / pinNumber.size() );
832
833 if( !nameVisible )
834 pin->SetNameTextSize( schIUScale.MilsToIU( 1 ) );
835
836 if( !numVisible )
837 pin->SetNumberTextSize( schIUScale.MilsToIU( 1 ) );
838
839 aSymbol->AddDrawItem( pin.release() );
840 }
841 else if( elType == wxS( "T" ) )
842 {
843 wxString textType = arr[1];
844 VECTOR2D pos( Convert( arr[2] ), Convert( arr[3] ) );
845 int angle = Convert( arr[4] );
846 // wxString color = arr[5];
847 wxString fontname = arr[6];
848 wxString fontSize = arr[7];
849 wxString baselineAlign = arr[10];
850 wxString textStr = arr[12];
851 bool visible = arr[13] != wxS( "0" );
852
853 textStr.Replace( wxS( "\\n" ), wxS( "\n" ) );
854 textStr = UnescapeHTML( textStr );
855
856 wxString halignStr = arr[14]; // Empty, start, middle, end, inherit
857
858 bool added = false;
859 EDA_TEXT* textItem = nullptr;
860
861 if( textType == wxS( "P" ) )
862 {
863 textItem = &aSymbol->GetReferenceField();
864 textItem->SetTextPos( RelPosSym( pos ) );
865 textItem->SetText( textStr );
866 }
867 else if( textType == wxS( "N" ) )
868 {
869 textItem = &aSymbol->GetValueField();
870 textItem->SetTextPos( RelPosSym( pos ) );
871 textItem->SetText( textStr );
872 }
873 else
874 {
875 textItem = new SCH_TEXT( RelPosSym( pos ), textStr, LAYER_DEVICE );
876 added = true;
877 }
878
879 textItem->SetTextAngleDegrees( ( 360 - angle ) % 360 );
881
882 if( halignStr == wxS( "middle" ) )
884 else if( halignStr == wxS( "end" ) )
886 else
888
889 textItem->SetFont( KIFONT::FONT::GetFont( fontname ) );
890 textItem->SetVisible( visible );
891
892 double ptSize = 7;
893
894 if( !fontSize.IsEmpty() )
895 {
896 if( fontSize.EndsWith( wxS( "pt" ) ) )
897 ptSize = Convert( fontSize.BeforeFirst( 'p' ) );
898 else if( fontSize.IsNumber() )
899 ptSize = Convert( fontSize );
900 }
901
902 double ktextSize = ScaleSize( ptSize );
903
904 if( textStr.Contains( wxS( "\n" ) ) )
905 ktextSize *= 0.8;
906 else
907 ktextSize *= 0.95;
908
909 textItem->SetTextSize( VECTOR2I( ktextSize, ktextSize ) );
910
911 TransformTextToBaseline( textItem, baselineAlign );
912
913 if( added )
914 aSymbol->AddDrawItem( dynamic_cast<SCH_ITEM*>( textItem ) );
915 }
916 }
917}
918
919
921 std::map<wxString, wxString> aParams,
922 wxArrayString aShapes )
923{
924 std::unique_ptr<LIB_SYMBOL> ksymbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
925
926 m_relOrigin = aOrigin;
927
928 std::optional<wxString> valOpt;
929 wxString symbolName = wxS( "Unknown" );
930
931 if( ( valOpt = get_opt( aParams, wxS( "name" ) ) ) )
932 symbolName = *valOpt;
933 else if( ( valOpt = get_opt( aParams, wxS( "spiceSymbolName" ) ) ) )
934 symbolName = *valOpt;
935
936 wxString symbolPrefix;
937
938 if( ( valOpt = get_opt( aParams, wxS( "pre" ) ) ) )
939 symbolPrefix = *valOpt;
940 else if( ( valOpt = get_opt( aParams, wxS( "spicePre" ) ) ) )
941 symbolPrefix = *valOpt;
942
943 LIB_ID libId = EasyEdaToKiCadLibID( wxEmptyString, symbolName );
944
945 ksymbol->SetLibId( libId );
946 ksymbol->SetName( symbolName );
947
948 ksymbol->GetReferenceField().SetText( symbolPrefix );
949 ksymbol->GetValueField().SetText( symbolName );
950
951 for( wxString attrName : c_attributesWhitelist )
952 {
953 wxString srcName = attrName;
954
955 if( srcName == wxS( "Datasheet" ) )
956 srcName = wxS( "link" );
957
958 if( ( valOpt = get_opt( aParams, srcName ) ) )
959 {
960 if( valOpt->empty() )
961 continue;
962
963 SCH_FIELD* fd = ksymbol->FindFieldCaseInsensitive( attrName );
964
965 if( !fd )
966 {
967 fd = new SCH_FIELD( ksymbol.get(), FIELD_T::USER, attrName );
968 ksymbol->AddField( fd );
969 }
970
971 fd->SetText( *valOpt );
972 fd->SetVisible( false );
973 }
974 }
975
976 ParseSymbolShapes( ksymbol.get(), aParams, aShapes );
977
978 return ksymbol.release();
979}
980
981std::pair<LIB_SYMBOL*, bool> SCH_EASYEDA_PARSER::MakePowerSymbol( const wxString& aFlagTypename,
982 const wxString& aNetname )
983{
984 std::unique_ptr<LIB_SYMBOL> ksymbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
985
987
988 LIB_ID libId = EasyEdaToKiCadLibID( wxEmptyString, aNetname );
989
990 ksymbol->SetGlobalPower();
991 ksymbol->SetLibId( libId );
992 ksymbol->SetName( aNetname );
993 ksymbol->GetReferenceField().SetText( wxS( "#PWR" ) );
994 ksymbol->GetReferenceField().SetVisible( false );
995 ksymbol->GetValueField().SetText( aNetname );
996 ksymbol->GetValueField().SetVisible( true );
997 ksymbol->SetDescription( wxString::Format( _( "Power symbol creates a global "
998 "label with name '%s'" ),
999 aNetname ) );
1000 ksymbol->SetKeyWords( wxS( "power-flag" ) );
1001 ksymbol->SetShowPinNames( false );
1002 ksymbol->SetShowPinNumbers( false );
1003
1004 std::unique_ptr<SCH_PIN> pin = std::make_unique<SCH_PIN>( ksymbol.get() );
1005
1006 pin->SetName( aNetname );
1007 pin->SetNumber( wxS( "1" ) );
1008 pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN );
1010 pin->SetLength( 0 );
1011
1012 ksymbol->AddDrawItem( pin.release() );
1013
1015
1016 bool flip = false;
1017
1018 if( aFlagTypename == wxS( "part_netLabel_gnD" ) )
1019 {
1021 }
1022 else if( aFlagTypename == wxS( "part_netLabel_GNd" ) )
1023 {
1025 }
1026 else if( aFlagTypename == wxS( "part_netLabel_gNd" ) )
1027 {
1029 }
1030 else if( aFlagTypename == wxS( "part_netLabel_GnD" ) )
1031 {
1033 }
1034 else if( aFlagTypename == wxS( "part_netLabel_VCC" ) )
1035 {
1037 flip = true;
1038 }
1039 else if( aFlagTypename == wxS( "part_netLabel_+5V" ) )
1040 {
1042 flip = true;
1043 }
1044 else if( aFlagTypename == wxS( "part_netLabel_VEE" ) )
1045 {
1047 }
1048 else if( aFlagTypename == wxS( "part_netLabel_-5V" ) )
1049 {
1051 }
1052 else if( aFlagTypename == wxS( "part_netLabel_Bar" ) )
1053 {
1055 flip = true;
1056 }
1057
1058 VECTOR2I valueFieldPos = HelperGeneratePowerPortGraphics( ksymbol.get(), flagStyle, nullptr );
1059 ksymbol->GetValueField().SetPosition( valueFieldPos );
1060
1061 return std::make_pair( ksymbol.release(), flip );
1062}
1063
1065 const wxString& aFileName, wxArrayString aShapes )
1066{
1067 std::map<wxString, std::unique_ptr<LIB_SYMBOL>> loadedSymbols;
1068 std::map<wxString, int> namesCounter;
1069 std::vector<std::unique_ptr<SCH_ITEM>> createdItems;
1070
1071 for( wxString shap : aShapes )
1072 {
1073 shap.Replace( wxS( "#@$" ), wxS( "\n" ) );
1074 wxArrayString parts = wxSplit( shap, '\n', '\0' );
1075
1076 if( parts.size() < 1 )
1077 continue;
1078
1079 wxArrayString arr = wxSplit( parts[0], '~', '\0' );
1080
1081 if( arr.size() < 1 )
1082 continue;
1083
1084 wxString rootType = arr[0];
1085
1086 if( rootType == wxS( "LIB" ) )
1087 {
1088 if( arr.size() < 4 )
1089 continue;
1090
1091 VECTOR2D origin( Convert( arr[1] ), Convert( arr[2] ) );
1092
1093 wxString symbolName = wxString::Format( wxS( "Unknown_%s_%s" ), arr[1], arr[2] );
1094
1095 wxArrayString paramParts = wxSplit( arr[3], '`', '\0' );
1096
1097 std::map<wxString, wxString> paramMap;
1098
1099 for( size_t i = 1; i < paramParts.size(); i += 2 )
1100 {
1101 wxString key = paramParts[i - 1];
1102 wxString value = paramParts[i];
1103
1104 if( key == wxS( "spiceSymbolName" ) && !value.IsEmpty() )
1105 symbolName = value;
1106
1107 paramMap[key] = value;
1108 }
1109
1110 int& serial = namesCounter[symbolName];
1111
1112 if( serial > 0 )
1113 symbolName << wxS( "_" ) << serial;
1114
1115 serial++;
1116
1117 paramMap[wxS( "spiceSymbolName" )] = symbolName;
1118
1119 parts.RemoveAt( 0 );
1120
1121 VECTOR2D pcbOrigin = m_relOrigin;
1122
1123 LIB_SYMBOL* sym = ParseSymbol( origin, paramMap, parts );
1124 loadedSymbols.emplace( symbolName, sym );
1125
1126 wxString referenceStr = sym->GetReferenceField().GetText();
1127
1128 m_relOrigin = pcbOrigin;
1129 LIB_ID libId = EasyEdaToKiCadLibID( wxEmptyString, symbolName );
1130
1131 std::unique_ptr<SCH_SYMBOL> schSym =
1132 std::make_unique<SCH_SYMBOL>( *sym, libId, &aSchematic->CurrentSheet(), 0 );
1133
1134 schSym->SetPosition( RelPos( origin ) );
1135 schSym->SetRef( &aSchematic->CurrentSheet(), referenceStr );
1136
1137 createdItems.push_back( std::move( schSym ) );
1138 }
1139 else if( rootType == wxS( "F" ) )
1140 {
1141 wxString sepShapeStr = parts[0];
1142 sepShapeStr.Replace( wxS( "^^" ), wxS( "\n" ) );
1143
1144 wxArrayString segments = wxSplit( sepShapeStr, '\n', '\0' );
1145 // wxArrayString mainParts = wxSplit( segments[0], '~', '\0' );
1146 // wxArrayString uselessParts = wxSplit( segments[1], '~', '\0' );
1147 wxArrayString valueParts = wxSplit( segments[2], '~', '\0' );
1148
1149 wxString flagTypename = arr[1];
1150 VECTOR2D pos( Convert( arr[2] ), Convert( arr[3] ) );
1151 double angle = Convert( arr[4] );
1152
1153 wxString netnameValue = valueParts[0];
1154 VECTOR2D valuePos( Convert( valueParts[2] ), Convert( valueParts[3] ) );
1155 double textAngle = Convert( valueParts[4] );
1156 wxString halignStr = valueParts[5];
1157 wxString valueFontname = valueParts[7];
1158 wxString valueFontsize = valueParts[8];
1159
1160 if( flagTypename == wxS( "part_netLabel_netPort" ) )
1161 {
1162 std::unique_ptr<SCH_GLOBALLABEL> label =
1163 std::make_unique<SCH_GLOBALLABEL>( RelPos( pos ), netnameValue );
1164
1166
1167 for( double i = angle; i > 0; i -= 90 )
1168 spin = spin.RotateCCW();
1169
1170 // If the shape was mirrored, we can't rely on angle value to determine direction.
1171 if( segments.size() > 3 )
1172 {
1173 wxArrayString shapeParts = wxSplit( segments[3], '~', '\0' );
1174 if( shapeParts[0] == wxS( "PL" ) )
1175 {
1176 wxArrayString ptArr = wxSplit( shapeParts[1], ' ', '\0' );
1177
1179
1180 for( size_t i = 1; i < ptArr.size(); i += 2 )
1181 {
1182 chain.Append( RelPos(
1183 VECTOR2I( Convert( ptArr[i - 1] ), Convert( ptArr[i] ) ) ) );
1184 }
1185
1186 chain.Move( -RelPos( pos ) );
1187
1188 VECTOR2I shapeCenter = chain.Centre();
1189
1190 if( std::abs( shapeCenter.x ) >= std::abs( shapeCenter.y ) )
1191 {
1192 if( shapeCenter.x >= 0 )
1193 spin = SPIN_STYLE::RIGHT;
1194 else
1195 spin = SPIN_STYLE::LEFT;
1196 }
1197 else
1198 {
1199 if( shapeCenter.y >= 0 )
1200 spin = SPIN_STYLE::BOTTOM;
1201 else
1202 spin = SPIN_STYLE::UP;
1203 }
1204 }
1205 }
1206
1207 label->SetSpinStyle( spin );
1208 label->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
1209
1210 createdItems.push_back( std::move( label ) );
1211 }
1212 else
1213 {
1214 auto pair = MakePowerSymbol( flagTypename, netnameValue );
1215 LIB_SYMBOL* pwrLibSym = pair.first;
1216 bool flip = pair.second;
1217
1218 LIB_ID libId = EasyEdaToKiCadLibID( wxEmptyString, netnameValue );
1219
1220 std::unique_ptr<SCH_SYMBOL> schSym = std::make_unique<SCH_SYMBOL>(
1221 *pwrLibSym, libId, &aSchematic->CurrentSheet(), 0 );
1222
1223 if( flip )
1224 schSym->SetOrientation( SYM_MIRROR_X );
1225
1226 if( angle == 0 )
1227 {
1228 }
1229 else if( angle == 90 )
1230 {
1231 schSym->SetOrientation( SYM_ROTATE_COUNTERCLOCKWISE );
1232 }
1233 if( angle == 180 )
1234 {
1235 schSym->SetOrientation( SYM_ROTATE_COUNTERCLOCKWISE );
1236 schSym->SetOrientation( SYM_ROTATE_COUNTERCLOCKWISE );
1237 }
1238 if( angle == 270 )
1239 {
1240 schSym->SetOrientation( SYM_ROTATE_CLOCKWISE );
1241 }
1242
1243 schSym->SetPosition( RelPos( pos ) );
1244
1245 SCH_FIELD* valField = schSym->GetField( FIELD_T::VALUE );
1246
1247 valField->SetPosition( RelPos( valuePos ) );
1248 valField->SetTextAngleDegrees( textAngle - angle );
1249
1250 if( !flip )
1252 else
1254
1255 if( halignStr == wxS( "middle" ) )
1257 else if( halignStr == wxS( "end" ) )
1259 else
1261
1262 if( flip && ( angle == 90 || angle == 270 ) )
1263 {
1264 if( valField->GetVertJustify() == GR_TEXT_V_ALIGN_BOTTOM )
1266 else if( valField->GetVertJustify() == GR_TEXT_V_ALIGN_TOP )
1268
1269 if( valField->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT )
1271 else if( valField->GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT )
1273
1274 if( flagTypename == wxS( "part_netLabel_Bar" ) ) // "Circle"
1276 }
1277
1278 if( angle == 0 && flagTypename == wxS( "part_netLabel_Bar" ) ) // "Circle"
1280
1281 valField->SetFont( KIFONT::FONT::GetFont( valueFontname ) );
1282
1283 double ptSize = 7;
1284
1285 if( valueFontsize.EndsWith( wxS( "pt" ) ) )
1286 ptSize = Convert( valueFontsize.BeforeFirst( 'p' ) );
1287
1288 double ktextSize = ScaleSize( ptSize );
1289
1290 if( netnameValue.Contains( wxS( "\n" ) ) )
1291 ktextSize *= 0.8;
1292 else
1293 ktextSize *= 0.95;
1294
1295 valField->SetTextSize( VECTOR2I( ktextSize, ktextSize ) );
1296
1297 //TransformTextToBaseline( valField, wxS( "" ), true );
1298
1299 createdItems.push_back( std::move( schSym ) );
1300 }
1301 }
1302 else if( rootType == wxS( "W" ) )
1303 {
1304 wxArrayString ptArr = wxSplit( arr[1], ' ', '\0' );
1305 //wxString strokeColor = arr[2];
1306 //double lineWidth = Convert( arr[3] );
1307 //LINE_STYLE strokeStyle = ConvertStrokeStyle( arr[4] );
1308 //wxString fillColor = arr[5].Lower();
1309 //bool locked = arr[7] != wxS( "0" );
1310
1312
1313 for( size_t i = 1; i < ptArr.size(); i += 2 )
1314 chain.Append( VECTOR2I( RelPosX( ptArr[i - 1] ), RelPosY( ptArr[i] ) ) );
1315
1316 for( int segId = 0; segId < chain.SegmentCount(); segId++ )
1317 {
1318 const SEG& seg = chain.CSegment( segId );
1319
1320 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>( seg.A, LAYER_WIRE );
1321 line->SetEndPoint( seg.B );
1322
1323 createdItems.push_back( std::move( line ) );
1324 }
1325 }
1326 else if( rootType == wxS( "N" ) )
1327 {
1328 VECTOR2D pos( Convert( arr[1] ), Convert( arr[2] ) );
1329 double angle = Convert( arr[3] );
1330 wxString netname = arr[5];
1331 wxString halignStr = arr[7];
1332 VECTOR2D text_pos( Convert( arr[8] ),
1333 Convert( arr[9] ) ); // TODO: detect top/bottom align
1334
1335 // wxString fontname = arr[10];
1336 // wxString fontSize = arr[11];
1337
1338 std::unique_ptr<SCH_LABEL> label =
1339 std::make_unique<SCH_LABEL>( RelPos( pos ), netname );
1340
1341 if( halignStr == wxS( "middle" ) )
1342 label->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
1343 else if( halignStr == wxS( "end" ) )
1344 label->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
1345 else
1346 label->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1347
1348 for( int left = angle; left > 0; left -= 90 )
1349 label->Rotate90( false );
1350
1351 createdItems.push_back( std::move( label ) );
1352 }
1353 else if( rootType == wxS( "O" ) )
1354 {
1355 VECTOR2D pos( Convert( arr[1] ), Convert( arr[2] ) );
1356
1357 std::unique_ptr<SCH_NO_CONNECT> noConn =
1358 std::make_unique<SCH_NO_CONNECT>( RelPos( pos ) );
1359
1360 createdItems.push_back( std::move( noConn ) );
1361 }
1362 else if( rootType == wxS( "J" ) )
1363 {
1364 VECTOR2D pos( Convert( arr[1] ), Convert( arr[2] ) );
1365 //double dia = Convert( arr[3] );
1366
1367 std::unique_ptr<SCH_JUNCTION> junction =
1368 std::make_unique<SCH_JUNCTION>( RelPos( pos ) /*, ScaleSizeUnit( dia )*/ );
1369
1370 createdItems.push_back( std::move( junction ) );
1371 }
1372 else if( rootType == wxS( "T" ) )
1373 {
1374 VECTOR2D pos( Convert( arr[2] ), Convert( arr[3] ) );
1375 int angle = Convert( arr[4] );
1376 // wxString color = arr[5];
1377 wxString fontname = arr[6];
1378 wxString fontSize = arr[7];
1379 wxString baselineAlign = arr[10];
1380 wxString textStr = arr[12];
1381
1382 textStr.Replace( wxS( "\\n" ), wxS( "\n" ) );
1383 textStr = UnescapeHTML( textStr );
1384
1385 wxString halignStr = arr[14]; // Empty, start, middle, end, inherit
1386
1387 std::unique_ptr<SCH_TEXT> textItem =
1388 std::make_unique<SCH_TEXT>( RelPos( pos ), textStr );
1389
1390 textItem->SetTextAngleDegrees( ( 360 - angle ) % 360 );
1391 textItem->SetVertJustify( GR_TEXT_V_ALIGN_TOP );
1392
1393 if( halignStr == wxS( "middle" ) )
1394 textItem->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER );
1395 else if( halignStr == wxS( "end" ) )
1396 textItem->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT );
1397 else
1398 textItem->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
1399
1400 textItem->SetFont( KIFONT::FONT::GetFont( fontname ) );
1401
1402 double ptSize = 7;
1403
1404 if( fontSize.EndsWith( wxS( "pt" ) ) )
1405 ptSize = Convert( fontSize.BeforeFirst( 'p' ) );
1406
1407 double ktextSize = ScaleSize( ptSize );
1408
1409 if( textStr.Contains( wxS( "\n" ) ) )
1410 ktextSize *= 0.8;
1411 else
1412 ktextSize *= 0.95;
1413
1414 textItem->SetTextSize( VECTOR2I( ktextSize, ktextSize ) );
1415
1416 TransformTextToBaseline( textItem.get(), baselineAlign );
1417
1418 createdItems.push_back( std::move( textItem ) );
1419 }
1420 else if( rootType == wxS( "R" ) )
1421 {
1422 VECTOR2D start( Convert( arr[1] ), Convert( arr[2] ) );
1423
1424 VECTOR2D cr;
1425 cr.x = !arr[3].empty() ? Convert( arr[3] ) : 0,
1426 cr.y = !arr[4].empty() ? Convert( arr[4] ) : 0; // TODO: corner radius
1427
1428 VECTOR2D size( Convert( arr[5] ), Convert( arr[6] ) );
1429 wxString strokeColor = arr[7];
1430 double lineWidth = Convert( arr[8] );
1431 LINE_STYLE strokeStyle = ConvertStrokeStyle( arr[9] );
1432 wxString fillColor = arr[10].Lower();
1433 //bool locked = arr[12] != wxS( "0" );
1434
1435 //if( cr.x == 0 )
1436 {
1437 std::unique_ptr<SCH_SHAPE> rect = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
1438
1439 rect->SetStart( RelPos( start ) );
1440 rect->SetEnd( RelPos( start + size ) );
1441
1442 rect->SetStroke( STROKE_PARAMS( ScaleSize( lineWidth ), strokeStyle ) );
1443
1444 if( fillColor != wxS( "none" ) )
1445 {
1446 rect->SetFilled( true );
1447
1448 if( fillColor == strokeColor )
1449 rect->SetFillMode( FILL_T::FILLED_SHAPE );
1450 else
1451 rect->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
1452 }
1453
1454 createdItems.push_back( std::move( rect ) );
1455 }
1456 /*else
1457 {
1458 }*/
1459 }
1460 else if( rootType == wxS( "I" ) )
1461 {
1462 VECTOR2D start( Convert( arr[1] ), Convert( arr[2] ) );
1463 VECTOR2D size( Convert( arr[3] ), Convert( arr[4] ) );
1464 //double angle = Convert( arr[5] ); // CSS-like transformations are used instead.
1465 wxString imageUrl = arr[6];
1466 wxString transformData = arr[9];
1467
1468 VECTOR2D kstart = RelPos( start );
1469 VECTOR2D ksize = ScalePos( size );
1470
1471 std::vector<std::pair<wxString, std::vector<double>>> transformCmds =
1472 ParseImageTransform( transformData );
1473
1474 auto applyTransform = [&]( SCH_ITEM* aSchItem )
1475 {
1476 for( const auto& cmd : transformCmds )
1477 {
1478 if( cmd.first == wxS( "rotate" ) )
1479 {
1480 if( cmd.second.size() != 3 )
1481 continue;
1482
1483 double cmdAngle = 360 - cmd.second[0];
1484 VECTOR2D cmdAround( cmd.second[1], cmd.second[2] );
1485
1486 for( double i = cmdAngle; i > 0; i -= 90 )
1487 {
1488 if( aSchItem->Type() == SCH_LINE_T )
1489 {
1490 // Lines need special handling for some reason
1491 aSchItem->SetFlags( STARTPOINT );
1492 aSchItem->Rotate( RelPos( cmdAround ), false );
1493 aSchItem->ClearFlags( STARTPOINT );
1494
1495 aSchItem->SetFlags( ENDPOINT );
1496 aSchItem->Rotate( RelPos( cmdAround ), false );
1497 aSchItem->ClearFlags( ENDPOINT );
1498 }
1499 else
1500 {
1501 aSchItem->Rotate( RelPos( cmdAround ), false );
1502 }
1503 }
1504 }
1505 else if( cmd.first == wxS( "translate" ) )
1506 {
1507 if( cmd.second.size() != 2 )
1508 continue;
1509
1510 VECTOR2D cmdOffset( cmd.second[0], cmd.second[1] );
1511 aSchItem->Move( ScalePos( cmdOffset ) );
1512 }
1513 else if( cmd.first == wxS( "scale" ) )
1514 {
1515 if( cmd.second.size() != 2 )
1516 continue;
1517
1518 double cmdScaleX = cmd.second[0];
1519 double cmdScaleY = cmd.second[1];
1520
1521 // Lines need special handling for some reason
1522 if( aSchItem->Type() == SCH_LINE_T )
1523 aSchItem->SetFlags( STARTPOINT | ENDPOINT );
1524
1525 if( cmdScaleX < 0 && cmdScaleY > 0 )
1526 {
1527 aSchItem->MirrorHorizontally( 0 );
1528 }
1529 else if( cmdScaleX > 0 && cmdScaleY < 0 )
1530 {
1531 aSchItem->MirrorVertically( 0 );
1532 }
1533 else if( cmdScaleX < 0 && cmdScaleY < 0 )
1534 {
1535 aSchItem->MirrorHorizontally( 0 );
1536 aSchItem->MirrorVertically( 0 );
1537 }
1538
1539 if( aSchItem->Type() == SCH_LINE_T )
1540 aSchItem->ClearFlags( STARTPOINT | ENDPOINT );
1541 }
1542 }
1543 };
1544
1545 if( imageUrl.BeforeFirst( ':' ) == wxS( "data" ) )
1546 {
1547 wxArrayString paramsArr =
1548 wxSplit( imageUrl.AfterFirst( ':' ).BeforeFirst( ',' ), ';', '\0' );
1549
1550 wxString data = imageUrl.AfterFirst( ',' );
1551
1552 if( paramsArr.size() > 0 )
1553 {
1554 wxString mimeType = paramsArr[0];
1555 wxMemoryBuffer buf = wxBase64Decode( data );
1556
1557 if( mimeType == wxS( "image/svg+xml" ) )
1558 {
1559 VECTOR2D offset = RelPos( start );
1560
1561 SVG_IMPORT_PLUGIN svgImportPlugin;
1562 GRAPHICS_IMPORTER_SCH schImporter;
1563
1564 svgImportPlugin.SetImporter( &schImporter );
1565 svgImportPlugin.LoadFromMemory( buf );
1566
1567 VECTOR2D imSize( svgImportPlugin.GetImageWidth(),
1568 svgImportPlugin.GetImageHeight() );
1569
1570 VECTOR2D pixelScale( schIUScale.IUTomm( ScaleSize( size.x ) ) / imSize.x,
1571 schIUScale.IUTomm( ScaleSize( size.y ) ) / imSize.y );
1572
1573 schImporter.SetScale( pixelScale );
1574
1575 VECTOR2D offsetMM( schIUScale.IUTomm( offset.x ),
1576 schIUScale.IUTomm( offset.y ) );
1577
1578 schImporter.SetImportOffsetMM( offsetMM );
1579
1580 svgImportPlugin.Import();
1581
1582 for( std::unique_ptr<EDA_ITEM>& item : schImporter.GetItems() )
1583 {
1584 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( item.release() );
1585
1586 applyTransform( schItem );
1587
1588 createdItems.emplace_back( schItem );
1589 }
1590 }
1591 else
1592 {
1593 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
1594 REFERENCE_IMAGE& refImage = bitmap->GetReferenceImage();
1595
1596 wxImage::SetDefaultLoadFlags( wxImage::GetDefaultLoadFlags()
1597 & ~wxImage::Load_Verbose );
1598
1599 if( refImage.ReadImageFile( buf ) )
1600 {
1601 VECTOR2D kcenter = kstart + ksize / 2;
1602
1603 double scaleFactor = ScaleSize( size.x ) / refImage.GetSize().x;
1604 refImage.SetImageScale( scaleFactor );
1605 bitmap->SetPosition( kcenter );
1606
1607 applyTransform( bitmap.get() );
1608
1609 createdItems.push_back( std::move( bitmap ) );
1610 }
1611 }
1612 }
1613 }
1614 }
1615 }
1616
1617 BOX2I sheetBBox;
1618
1619 for( std::unique_ptr<SCH_ITEM>& ptr : createdItems )
1620 if( ptr->Type() == SCH_SYMBOL_T )
1621 sheetBBox.Merge( static_cast<SCH_SYMBOL*>( ptr.get() )->GetBodyBoundingBox() );
1622
1623 SCH_SCREEN* screen = aRootSheet->GetScreen();
1624 PAGE_INFO pageInfo = screen->GetPageSettings();
1625
1626 int alignGrid = schIUScale.MilsToIU( 50 );
1627
1628 VECTOR2D offset( -sheetBBox.GetLeft(), -sheetBBox.GetTop() );
1629 offset.x = KiROUND( offset.x / alignGrid ) * alignGrid;
1630 offset.y = KiROUND( offset.y / alignGrid ) * alignGrid;
1631
1632 pageInfo.SetWidthMils( schIUScale.IUToMils( sheetBBox.GetWidth() ) );
1633 pageInfo.SetHeightMils( schIUScale.IUToMils( sheetBBox.GetHeight() ) );
1634
1635 screen->SetPageSettings( pageInfo );
1636
1637 for( std::unique_ptr<SCH_ITEM>& ptr : createdItems )
1638 {
1639 ptr->Move( offset );
1640 screen->Append( ptr.release() );
1641 }
1642}
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:130
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
constexpr size_type GetWidth() const
Definition box2.h:211
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:594
constexpr size_type GetHeight() const
Definition box2.h:212
constexpr coord_type GetLeft() const
Definition box2.h:225
constexpr coord_type GetTop() const
Definition box2.h:226
static double Convert(const wxString &aValue)
double RelPosX(double aValue)
double RelPosY(double aValue)
VECTOR2< T > RelPos(const VECTOR2< T > &aVec)
VECTOR2< T > ScalePos(const VECTOR2< T > &aValue)
void TransformTextToBaseline(EDA_TEXT *textItem, const wxString &baselineAlign)
std::vector< SHAPE_LINE_CHAIN > ParseLineChains(const wxString &aData, int aMaxError, bool aForceClosed)
virtual void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:329
virtual void SetBezierC2(const VECTOR2I &aPt)
Definition eda_shape.h:367
virtual void SetBezierC1(const VECTOR2I &aPt)
Definition eda_shape.h:364
virtual void SetStart(const VECTOR2I &aStart)
Definition eda_shape.h:279
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
virtual void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:512
virtual void SetTextPos(const VECTOR2I &aPoint)
Definition eda_text.cpp:556
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition eda_text.cpp:378
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:239
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:347
void SetTextAngleDegrees(double aOrientation)
Definition eda_text.h:181
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition eda_text.h:242
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:236
void SetFont(KIFONT::FONT *aFont)
Definition eda_text.cpp:471
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:370
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, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition font.cpp:143
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
Define a library symbol object.
Definition lib_symbol.h:114
SCH_FIELD & GetValueField()
Definition lib_symbol.h:447
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
SCH_FIELD & GetReferenceField()
Definition lib_symbol.h:451
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition page_info.h:75
void SetHeightMils(double aHeightInMils)
void SetWidthMils(double aWidthInMils)
A progress reporter interface for use in multi-threaded environments.
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
VECTOR2I GetSize() const
void SetImageScale(double aScale)
Set the image "zoom" value.
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition reporter.h:102
Holds all the data relating to one schematic.
Definition schematic.h:149
SCH_SHEET_PATH & CurrentSheet() const
Definition schematic.h:304
void ParseSymbolShapes(LIB_SYMBOL *aContainer, std::map< wxString, wxString > paramMap, wxArrayString aShapes)
std::pair< LIB_SYMBOL *, bool > MakePowerSymbol(const wxString &aFlagTypename, const wxString &aNetname)
double ScaleSize(double aValue) override
void ParseSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const wxString &aFileName, wxArrayString aShapes)
VECTOR2< T > RelPosSym(const VECTOR2< T > &aVec)
LIB_SYMBOL * ParseSymbol(const VECTOR2D &aOrigin, std::map< wxString, wxString > aParams, wxArrayString aShapes)
SCH_EASYEDA_PARSER(SCHEMATIC *aSchematic, PROGRESS_REPORTER *aProgressReporter)
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:139
void SetPosition(const VECTOR2I &aPosition) override
void SetText(const wxString &aText) override
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
const PAGE_INFO & GetPageSettings() const
Definition sch_screen.h:144
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition sch_screen.h:145
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition sch_shape.cpp:98
void AddPoint(const VECTOR2I &aPosition)
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:145
Schematic symbol object.
Definition sch_symbol.h:73
BOX2I GetBodyBoundingBox() const override
Return a bounding box for the symbol body but not the pins or fields.
Definition seg.h:38
VECTOR2I A
Definition seg.h:45
VECTOR2I B
Definition seg.h:46
const VECTOR2I & GetArcMid() const
Definition shape_arc.h:116
const VECTOR2I & GetP1() const
Definition shape_arc.h:115
const VECTOR2I & GetP0() const
Definition shape_arc.h:114
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Spin style for labels of all kinds on schematics.
Definition sch_label.h:38
SPIN_STYLE RotateCCW()
Simple container to manage line stroke parameters.
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.
#define _(s)
@ FILLED_WITH_BG_BODYCOLOR
Definition eda_fill.h:32
@ FILLED_SHAPE
Fill with object color.
Definition eda_fill.h:31
#define ENDPOINT
ends. (Used to support dragging.)
#define STARTPOINT
When a line is selected, these flags indicate which.
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:57
void ConvertImageToLibShapes(LIB_SYMBOL *aSymbol, int unit, wxImage img, VECTOR2D pixelScale, VECTOR2D offset)
@ LAYER_DEVICE
Definition layer_ids.h:488
@ LAYER_WIRE
Definition layer_ids.h:474
std::optional< V > get_opt(const std::map< wxString, V > &aMap, const wxString &aKey)
Definition map_helpers.h:30
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:437
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_OUTPUT
usual output
Definition pin_type.h:34
@ PT_BIDI
input or output (like port for a microprocessor)
Definition pin_type.h:35
@ 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
@ RPT_SEVERITY_WARNING
static std::vector< std::vector< wxString > > RegexMatchAll(wxRegEx &aRegex, const wxString &aString)
static const std::vector< wxString > c_attributesWhitelist
static ELECTRICAL_PINTYPE ConvertElecType(const wxString &aType)
VECTOR2I HelperGeneratePowerPortGraphics(LIB_SYMBOL *aKsymbol, EASYEDA::POWER_FLAG_STYLE aStyle, REPORTER *aReporter)
static LIB_ID EasyEdaToKiCadLibID(const wxString &aLibName, const wxString &aLibReference)
static std::vector< std::pair< wxString, std::vector< double > > > ParseImageTransform(const wxString &transformData)
EasyEDA image transformations are in the form of:
static LINE_STYLE ConvertStrokeStyle(const wxString &aStyle)
VECTOR2I HelperGeneratePowerPortGraphics(LIB_SYMBOL *aKsymbol, ASCH_POWER_PORT_STYLE aStyle, REPORTER *aReporter)
@ L_INPUT
Definition sch_label.h:98
const int scale
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
wxString UnescapeHTML(const wxString &aString)
Return a new wxString unescaped from HTML format.
@ CTX_LIBID
LINE_STYLE
Dashed line types.
@ SYM_ROTATE_CLOCKWISE
Definition symbol.h:34
@ SYM_ROTATE_COUNTERCLOCKWISE
Definition symbol.h:35
@ SYM_MIRROR_X
Definition symbol.h:40
@ USER
The field ID hasn't been set yet; field is invalid.
@ VALUE
Field Value of part, i.e. "3.3K".
KIBIS_PIN * pin
VECTOR2I center
const SHAPE_LINE_CHAIN chain
int radius
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
@ SCH_LINE_T
Definition typeinfo.h:159
@ SCH_SYMBOL_T
Definition typeinfo.h:168
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707