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