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