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