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