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