KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcad2kicad_common.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) 2007, 2008 Lubo Racko <[email protected]>
5 * Copyright (C) 2008, 2012 Alexander Lunev <[email protected]>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
25
27
28#include <common.h>
29#include <math/util.h> // for KiROUND
30#include <trigo.h>
31#include <xnode.h>
32
33#include <wx/regex.h>
34
35namespace PCAD2KICAD {
36
37// PCAD stroke font average ratio of width to size
38const double TEXT_WIDTH_TO_SIZE_AVERAGE = 0.5;
39
40// PCAD proportions of stroke font
41const double STROKE_HEIGHT_TO_SIZE = 0.656;
42const double STROKE_WIDTH_TO_SIZE = 0.69;
43
44// TrueType font
45const double TRUETYPE_HEIGHT_TO_SIZE = 0.585;
46const double TRUETYPE_WIDTH_TO_SIZE = 0.585;
47const double TRUETYPE_THICK_PER_HEIGHT = 0.073;
48const double TRUETYPE_BOLD_THICK_MUL = 1.6;
49const long TRUETYPE_BOLD_MIN_WEIGHT = 700;
50
51
52wxString GetWord( wxString* aStr )
53{
54 wxString result = wxEmptyString;
55
56 *aStr = aStr->Trim( false );
57
58 if( aStr->Len() == 0 )
59 return result;
60
61 if( (*aStr)[0] == wxT( '"' ) )
62 {
63 result += (*aStr)[0];
64 *aStr = aStr->Mid( 1 ); // remove Frot apostrofe
65
66 while( aStr->Len() > 0 && (*aStr)[0] != wxT( '"' ) )
67 {
68 result += (*aStr)[0];
69 *aStr = aStr->Mid( 1 );
70 }
71
72 if( aStr->Len() > 0 && (*aStr)[0] == wxT( '"' ) )
73 {
74 result += (*aStr)[0];
75 *aStr = aStr->Mid( 1 ); // remove ending apostrophe
76 }
77 }
78 else
79 {
80 while( aStr->Len() > 0
81 && !( (*aStr)[0] == wxT( ' ' )
82 || (*aStr)[0] == wxT( '(' )
83 || (*aStr)[0] == wxT( ')' ) ) )
84 {
85 result += (*aStr)[0];
86 *aStr = aStr->Mid( 1 );
87 }
88 }
89
90 result.Trim( true );
91 result.Trim( false );
92
93 return result;
94}
95
96
98{
99 XNODE* result, * lNode;
100
101 result = nullptr;
102 lNode = FindNode( aNode, wxT( "attachedPattern" ) );
103
104 if( lNode )
105 result = FindNode( lNode, wxT( "padPinMap" ) );
106
107 return result;
108}
109
110
111double StrToDoublePrecisionUnits( const wxString& aStr, char aAxe,
112 const wxString& aActualConversion )
113{
114 wxString ls;
115 double i;
116 char u;
117
118 ls = aStr;
119 ls.Trim( true );
120 ls.Trim( false );
121
122 if( ls.Len() > 0 )
123 {
124 u = ls[ls.Len() - 1];
125
126 while( ls.Len() > 0
127 && !( ls[ls.Len() - 1] == wxT( '.' )
128 || ls[ls.Len() - 1] == wxT( ',' )
129 || (ls[ls.Len() - 1] >= wxT( '0' ) && ls[ls.Len() - 1] <= wxT( '9' ) ) ) )
130 {
131 ls = ls.Left( ls.Len() - 1 );
132 }
133
134 while( ls.Len() > 0
135 && !( ls[0] == wxT( '-' )
136 || ls[0] == wxT( '+' )
137 || ls[0] == wxT( '.' )
138 || ls[0] == wxT( ',' )
139 || (ls[0] >= wxT( '0' ) && ls[0] <= wxT( '9' ) ) ) )
140 {
141 ls = ls.Mid( 1 );
142 }
143
144 if( u == wxT( 'm' ) )
145 {
146 ls.ToCDouble( &i );
147
148#ifdef PCAD2KICAD_SCALE_SCH_TO_INCH_GRID
149 if( aActualConversion == wxT( "SCH" )
150 || aActualConversion == wxT( "SCHLIB" ) )
151 i = i * (0.0254 / 0.025);
152#endif
153
154 i = pcbIUScale.mmToIU( i );
155 }
156 else
157 {
158 ls.ToCDouble( &i );
159 i *= pcbIUScale.IU_PER_MILS;
160 }
161 }
162 else
163 {
164 i = 0.0;
165 }
166
167 if( ( aActualConversion == wxT( "PCB" ) || aActualConversion == wxT( "SCH" ) )
168 && aAxe == wxT( 'Y' ) )
169 return -i;
170 else
171 return i; // Y axe is mirrored compared to P-Cad
172}
173
174
175int StrToIntUnits( const wxString& aStr, char aAxe, const wxString& aActualConversion )
176{
177 return KiROUND( StrToDoublePrecisionUnits( aStr, aAxe, aActualConversion ) );
178}
179
180
181wxString GetAndCutWordWithMeasureUnits( wxString* aStr, const wxString& aDefaultMeasurementUnit )
182{
183 wxString result;
184
185 aStr->Trim( false );
186 result = wxEmptyString;
187
188 // value
189 while( aStr->Len() > 0 && (*aStr)[0] != wxT( ' ' ) )
190 {
191 result += (*aStr)[0];
192 *aStr = aStr->Mid( 1 );
193 }
194
195 aStr->Trim( false );
196
197 // if there is also measurement unit
198 while( aStr->Len() > 0
199 && ( ( (*aStr)[0] >= wxT( 'a' ) && (*aStr)[0] <= wxT( 'z' ) )
200 || ( (*aStr)[0] >= wxT( 'A' ) && (*aStr)[0] <= wxT( 'Z' ) ) ) )
201 {
202 result += (*aStr)[0];
203 *aStr = aStr->Mid( 1 );
204 }
205
206 // and if not, add default....
207 if( result.Len() > 0
208 && ( result[result.Len() - 1] == wxT( '.' )
209 || result[result.Len() - 1] == wxT( ',' )
210 || (result[result.Len() - 1] >= wxT( '0' )
211 && result[result.Len() - 1] <= wxT( '9' ) ) ) )
212 {
213 result += aDefaultMeasurementUnit;
214 }
215
216 return result;
217}
218
219
220int StrToInt1Units( const wxString& aStr )
221{
222 double num, precision = 10;
223
224 aStr.ToCDouble( &num );
225 return KiROUND( num * precision );
226}
227
228
229wxString ValidateName( const wxString& aName )
230{
231 wxString retv = aName;
232 retv.Replace( wxT( " " ), wxT( "_" ) );
233
234 return retv;
235}
236
237
238wxString ValidateReference( const wxString& aRef )
239{
240 wxRegEx reRef;
241 reRef.Compile( wxT( "^[[:digit:]][[:digit:]]*$" ) );
242
243 wxString retv = aRef;
244
245 if( reRef.Matches( retv ) )
246 retv.Prepend( wxT( '.' ) );
247
248 return retv;
249}
250
251
252void SetWidth( const wxString& aStr, const wxString& aDefaultMeasurementUnit, int* aWidth,
253 const wxString& aActualConversion )
254{
255 wxString tmp = aStr;
256
257 *aWidth = StrToIntUnits( GetAndCutWordWithMeasureUnits( &tmp, aDefaultMeasurementUnit ),
258 wxT( ' ' ), aActualConversion );
259}
260
261
262void SetHeight( const wxString& aStr, const wxString& aDefaultMeasurementUnit, int* aHeight,
263 const wxString& aActualConversion )
264{
265 wxString tmp = aStr;
266
267 *aHeight = StrToIntUnits( GetAndCutWordWithMeasureUnits( &tmp, aDefaultMeasurementUnit ),
268 wxT( ' ' ), aActualConversion );
269}
270
271
272void SetPosition( const wxString& aStr, const wxString& aDefaultMeasurementUnit, int* aX, int* aY,
273 const wxString& aActualConversion )
274{
275 wxString tmp = aStr;
276
277 *aX = StrToIntUnits( GetAndCutWordWithMeasureUnits( &tmp, aDefaultMeasurementUnit ),
278 wxT( 'X' ), aActualConversion );
279 *aY = StrToIntUnits( GetAndCutWordWithMeasureUnits( &tmp, aDefaultMeasurementUnit ),
280 wxT( 'Y' ), aActualConversion );
281}
282
283
284void SetDoublePrecisionPosition( const wxString& aStr, const wxString& aDefaultMeasurementUnit,
285 double* aX, double* aY, const wxString& aActualConversion )
286{
287 wxString tmp = aStr;
288
290 GetAndCutWordWithMeasureUnits( &tmp, aDefaultMeasurementUnit ), wxT( 'X' ),
291 aActualConversion );
293 GetAndCutWordWithMeasureUnits( &tmp, aDefaultMeasurementUnit ), wxT( 'Y' ),
294 aActualConversion );
295}
296
297
298TTEXT_JUSTIFY GetJustifyIdentificator( const wxString& aJustify )
299{
300 TTEXT_JUSTIFY id;
301
302 if( aJustify.IsSameAs( wxT( "LowerCenter" ), false ) )
303 id = LowerCenter;
304 else if( aJustify.IsSameAs( wxT( "LowerRight" ), false ) )
305 id = LowerRight;
306 else if( aJustify.IsSameAs( wxT( "UpperLeft" ), false ) )
307 id = UpperLeft;
308 else if( aJustify.IsSameAs( wxT( "UpperCenter" ), false ) )
309 id = UpperCenter;
310 else if( aJustify.IsSameAs( wxT( "UpperRight" ), false ) )
311 id = UpperRight;
312 else if( aJustify.IsSameAs( wxT( "Left" ), false ) )
313 id = Left;
314 else if( aJustify.IsSameAs( wxT( "Center" ), false ) )
315 id = Center;
316 else if( aJustify.IsSameAs( wxT( "Right" ), false ) )
317 id = Right;
318 else
319 id = LowerLeft;
320
321 return id;
322}
323
324
325void SetTextParameters( XNODE* aNode, TTEXTVALUE* aTextValue,
326 const wxString& aDefaultMeasurementUnit, const wxString& aActualConversion )
327{
328 XNODE* tNode;
329 wxString str;
330
331 tNode = FindNode( aNode, wxT( "pt" ) );
332
333 if( tNode )
334 SetPosition( tNode->GetNodeContent(), aDefaultMeasurementUnit, &aTextValue->textPositionX,
335 &aTextValue->textPositionY, aActualConversion );
336
337 tNode = FindNode( aNode, wxT( "rotation" ) );
338
339 if( tNode )
340 {
341 str = tNode->GetNodeContent();
342 str.Trim( false );
344 }
345 else
346 {
347 aTextValue->textRotation = ANGLE_0;
348 }
349
350 str = FindNodeGetContent( aNode, wxT( "isVisible" ) );
351
352 if( str.IsSameAs( wxT( "True" ), false ) )
353 aTextValue->textIsVisible = 1;
354 else
355 aTextValue->textIsVisible = 0;
356
357 str = FindNodeGetContent( aNode, wxT( "justify" ) );
358 aTextValue->justify = GetJustifyIdentificator( str );
359
360 str = FindNodeGetContent( aNode, wxT( "isFlipped" ) );
361
362 if( str.IsSameAs( wxT( "True" ), false ) )
363 aTextValue->mirror = 1;
364 else
365 aTextValue->mirror = 0;
366
367 tNode = FindNode( aNode, wxT( "textStyleRef" ) );
368
369 if( tNode )
370 SetFontProperty( tNode, aTextValue, aDefaultMeasurementUnit, aActualConversion );
371}
372
373
374void SetFontProperty( XNODE* aNode, TTEXTVALUE* aTextValue, const wxString& aDefaultMeasurementUnit,
375 const wxString& aActualConversion )
376{
377 wxString n, propValue;
378
379 aNode->GetAttribute( wxT( "Name" ), &n );
380
381 while( aNode->GetName() != wxT( "www.lura.sk" ) )
382 aNode = aNode->GetParent();
383
384 aNode = FindNode( aNode, wxT( "library" ) );
385
386 if( aNode )
387 aNode = FindNode( aNode, wxT( "textStyleDef" ) );
388
389 while( aNode )
390 {
391 aNode->GetAttribute( wxT( "Name" ), &propValue );
392 propValue.Trim( false );
393 propValue.Trim( true );
394
395 if( propValue == n )
396 break;
397
398 aNode = aNode->GetNext();
399 }
400
401 if( aNode )
402 {
403 wxString fontType;
404
405 propValue = FindNodeGetContent( aNode, wxT( "textStyleDisplayTType" ) );
406 aTextValue->isTrueType = ( propValue.IsSameAs( wxT( "True" ), false ) );
407
408 aNode = FindNode( aNode, wxT( "font" ) );
409 fontType = FindNodeGetContent( aNode, wxT( "fontType" ) );
410
411 if( ( aTextValue->isTrueType && !fontType.IsSameAs( wxT( "TrueType" ), false ) ) ||
412 ( !aTextValue->isTrueType && !fontType.IsSameAs( wxT( "Stroke" ), false ) ) )
413 aNode = aNode->GetNext();
414
415 if( aNode )
416 {
417 if( aTextValue->isTrueType )
418 {
419 propValue = FindNodeGetContent( aNode, wxT( "fontItalic" ) );
420 aTextValue->isItalic = propValue.IsSameAs( wxT( "True" ), false );
421
422 propValue = FindNodeGetContent( aNode, wxT( "fontWeight" ) );
423
424 if( propValue != wxEmptyString )
425 {
426 long fontWeight;
427
428 propValue.ToLong( &fontWeight );
429 aTextValue->isBold = ( fontWeight >= TRUETYPE_BOLD_MIN_WEIGHT );
430 }
431 }
432
433 XNODE* lNode;
434
435 lNode = FindNode( aNode, wxT( "fontHeight" ) );
436
437 if( lNode )
438 SetHeight( lNode->GetNodeContent(), aDefaultMeasurementUnit,
439 &aTextValue->textHeight, aActualConversion );
440
441 if( aTextValue->isTrueType )
442 {
443 aTextValue->textstrokeWidth = TRUETYPE_THICK_PER_HEIGHT * aTextValue->textHeight;
444
445 if( aTextValue->isBold )
447 }
448 else
449 {
450 lNode = FindNode( aNode, wxT( "strokeWidth" ) );
451
452 if( lNode )
453 SetWidth( lNode->GetNodeContent(), aDefaultMeasurementUnit,
454 &aTextValue->textstrokeWidth, aActualConversion );
455 }
456 }
457 }
458}
459
460
461void SetTextJustify( EDA_TEXT* aText, TTEXT_JUSTIFY aJustify )
462{
463 switch( aJustify )
464 {
465 case LowerLeft:
468 break;
469 case LowerCenter:
472 break;
473 case LowerRight:
476 break;
477 case UpperLeft:
480 break;
481 case UpperCenter:
484 break;
485 case UpperRight:
488 break;
489 case Left:
492 break;
493 case Center:
496 break;
497 case Right:
500 break;
501 }
502}
503
504
506{
507 return KiROUND( (double) aText->text.Len() *
508 (double) aText->textHeight * TEXT_WIDTH_TO_SIZE_AVERAGE );
509}
510
511
513{
514 int cm = aValue->mirror ? -1 : 1;
515 int cl = KiROUND( (double) CalculateTextLengthSize( aValue ) / 2.0 );
516 int ch = KiROUND( (double) aValue->textHeight / 2.0 );
517 int posX = 0;
518 int posY = 0;
519
520 if( aValue->justify == LowerLeft || aValue->justify == Left || aValue->justify == UpperLeft )
521 posX += cl * cm;
522 else if( aValue->justify == LowerRight || aValue->justify == Right ||
523 aValue->justify == UpperRight )
524 posX -= cl * cm;
525
526 if( aValue->justify == LowerLeft || aValue->justify == LowerCenter ||
527 aValue->justify == LowerRight )
528 posY -= ch;
529 else if( aValue->justify == UpperLeft || aValue->justify == UpperCenter ||
530 aValue->justify == UpperRight )
531 posY += ch;
532
533 RotatePoint( &posX, &posY, aValue->textRotation );
534
535 aValue->correctedPositionX = aValue->textPositionX + posX;
536 aValue->correctedPositionY = aValue->textPositionY + posY;
537}
538
539
540void SetTextSizeFromStrokeFontHeight( EDA_TEXT* aText, int aTextHeight )
541{
542 aText->SetTextSize( KiROUND( aTextHeight * STROKE_WIDTH_TO_SIZE, aTextHeight * STROKE_HEIGHT_TO_SIZE ) );
543}
544
545
546void SetTextSizeFromTrueTypeFontHeight( EDA_TEXT* aText, int aTextHeight )
547{
548 aText->SetTextSize( KiROUND( aTextHeight * TRUETYPE_WIDTH_TO_SIZE, aTextHeight * TRUETYPE_HEIGHT_TO_SIZE ) );
549}
550
551
552XNODE* FindNode( XNODE* aChild, const wxString& aTag )
553{
554 aChild = aChild->GetChildren();
555
556 while( aChild )
557 {
558 if( aChild->GetName().IsSameAs( aTag, false ) )
559 return aChild;
560
561 aChild = aChild->GetNext();
562 }
563
564 return nullptr;
565}
566
567
568wxString FindNodeGetContent( XNODE* aChild, const wxString& aTag )
569{
570 wxString str = wxEmptyString;
571
572 aChild = FindNode( aChild, aTag );
573
574 if( aChild )
575 {
576 str = aChild->GetNodeContent();
577 str.Trim( false );
578 str.Trim( true );
579 }
580
581 return str;
582}
583
584
585void InitTTextValue( TTEXTVALUE* aTextValue )
586{
587 aTextValue->text = wxEmptyString;
588 aTextValue->textPositionX = 0;
589 aTextValue->textPositionY = 0;
590 aTextValue->textRotation = ANGLE_0;
591 aTextValue->textHeight = 0;
592 aTextValue->textstrokeWidth = 0;
593 aTextValue->textIsVisible = 0;
594 aTextValue->mirror = 0;
595 aTextValue->textUnit = 0;
596 aTextValue->correctedPositionX = 0;
597 aTextValue->correctedPositionY = 0;
598 aTextValue->justify = LowerLeft;
599 aTextValue->isBold = false;
600 aTextValue->isItalic = false;
601 aTextValue->isTrueType = false;
602}
603
604} // namespace PCAD2KICAD
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:986
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
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition eda_text.cpp:412
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:404
An extension of wxXmlNode that can format its contents as KiCad-style s-expressions.
Definition xnode.h:67
XNODE * GetParent() const
Definition xnode.h:107
XNODE * GetChildren() const
Definition xnode.h:97
XNODE * GetNext() const
Definition xnode.h:102
The common library.
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
@ TENTHS_OF_A_DEGREE_T
Definition eda_angle.h:30
wxString ValidateName(const wxString &aName)
wxString GetWord(wxString *aStr)
int StrToIntUnits(const wxString &aStr, char aAxe, const wxString &aActualConversion)
int StrToInt1Units(const wxString &aStr)
void SetWidth(const wxString &aStr, const wxString &aDefaultMeasurementUnit, int *aWidth, const wxString &aActualConversion)
void SetHeight(const wxString &aStr, const wxString &aDefaultMeasurementUnit, int *aHeight, const wxString &aActualConversion)
XNODE * FindNode(XNODE *aChild, const wxString &aTag)
const double TRUETYPE_THICK_PER_HEIGHT
double StrToDoublePrecisionUnits(const wxString &aStr, char aAxe, const wxString &aActualConversion)
wxString ValidateReference(const wxString &aRef)
const double STROKE_WIDTH_TO_SIZE
void SetTextSizeFromStrokeFontHeight(EDA_TEXT *aText, int aTextHeight)
const double TRUETYPE_BOLD_THICK_MUL
void SetPosition(const wxString &aStr, const wxString &aDefaultMeasurementUnit, int *aX, int *aY, const wxString &aActualConversion)
void SetDoublePrecisionPosition(const wxString &aStr, const wxString &aDefaultMeasurementUnit, double *aX, double *aY, const wxString &aActualConversion)
TTEXT_JUSTIFY GetJustifyIdentificator(const wxString &aJustify)
const double TRUETYPE_HEIGHT_TO_SIZE
void SetTextJustify(EDA_TEXT *aText, TTEXT_JUSTIFY aJustify)
const double STROKE_HEIGHT_TO_SIZE
int CalculateTextLengthSize(TTEXTVALUE *aText)
XNODE * FindPinMap(XNODE *aNode)
void CorrectTextPosition(TTEXTVALUE *aValue)
const double TEXT_WIDTH_TO_SIZE_AVERAGE
const long TRUETYPE_BOLD_MIN_WEIGHT
void SetFontProperty(XNODE *aNode, TTEXTVALUE *aTextValue, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion)
wxString FindNodeGetContent(XNODE *aChild, const wxString &aTag)
void SetTextParameters(XNODE *aNode, TTEXTVALUE *aTextValue, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion)
wxString GetAndCutWordWithMeasureUnits(wxString *aStr, const wxString &aDefaultMeasurementUnit)
void InitTTextValue(TTEXTVALUE *aTextValue)
void SetTextSizeFromTrueTypeFontHeight(EDA_TEXT *aText, int aTextHeight)
const double TRUETYPE_WIDTH_TO_SIZE
wxString result
Test unit parsing edge cases and error handling.
@ 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:225