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 KiCad Developers, see CHANGELOG.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 <wx/wx.h>
31 #include <wx/regex.h>
32 
33 #include <common.h>
34 #include <convert_to_biu.h>
35 #include <math/util.h> // for KiROUND
36 
37 #include <pcad2kicad_common.h>
38 
39 namespace PCAD2KICAD {
40 
41 // PCAD stroke font average ratio of width to size
42 const double TEXT_WIDTH_TO_SIZE_AVERAGE = 0.5;
43 // PCAD proportions of stroke font
44 const double STROKE_HEIGHT_TO_SIZE = 0.656;
45 const double STROKE_WIDTH_TO_SIZE = 0.69;
46 // TrueType font
47 const double TRUETYPE_HEIGHT_TO_SIZE = 0.585;
48 const double TRUETYPE_WIDTH_TO_SIZE = 0.585;
49 const double TRUETYPE_THICK_PER_HEIGHT = 0.073;
50 const double TRUETYPE_BOLD_THICK_MUL = 1.6;
51 const long TRUETYPE_BOLD_MIN_WEIGHT = 700;
52 
53 wxString 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 = NULL;
103  lNode = FindNode( aNode, wxT( "attachedPattern" ) );
104 
105  if( lNode )
106  result = FindNode( lNode, wxT( "padPinMap" ) );
107 
108  return result;
109 }
110 
111 
112 double StrToDoublePrecisionUnits( const wxString& aStr, char aAxe, 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.ToDouble( &i );
147 #ifdef PCAD2KICAD_SCALE_SCH_TO_INCH_GRID
148  if( aActualConversion == wxT( "SCH" )
149  || aActualConversion == wxT( "SCHLIB" ) )
150  i = i * (0.0254 / 0.025);
151 #endif
152  i = Millimeter2iu( i );
153  }
154  else
155  {
156  ls.ToDouble( &i );
157  i = Mils2iu( i );
158  }
159  }
160  else
161  i = 0.0;
162 
163  if( ( aActualConversion == wxT( "PCB" ) || aActualConversion == wxT( "SCH" ) )
164  && aAxe == wxT( 'Y' ) )
165  return -i;
166  else
167  return i; // Y axe is mirrored compared to P-Cad
168 }
169 
170 
171 int StrToIntUnits( const wxString& aStr, char aAxe, const wxString& aActualConversion )
172 {
173  return KiROUND( StrToDoublePrecisionUnits( aStr, aAxe, aActualConversion ) );
174 }
175 
176 
177 wxString GetAndCutWordWithMeasureUnits( wxString* aStr, const wxString& aDefaultMeasurementUnit )
178 {
179  wxString result;
180 
181  aStr->Trim( false );
182  result = wxEmptyString;
183 
184  // value
185  while( aStr->Len() > 0 && (*aStr)[0] != wxT( ' ' ) )
186  {
187  result += (*aStr)[0];
188  *aStr = aStr->Mid( 1 );
189  }
190 
191  aStr->Trim( false );
192 
193  // if there is also measurement unit
194  while( aStr->Len() > 0
195  && ( ( (*aStr)[0] >= wxT( 'a' ) && (*aStr)[0] <= wxT( 'z' ) )
196  || ( (*aStr)[0] >= wxT( 'A' ) && (*aStr)[0] <= wxT( 'Z' ) ) ) )
197  {
198  result += (*aStr)[0];
199  *aStr = aStr->Mid( 1 );
200  }
201 
202  // and if not, add default....
203  if( result.Len() > 0
204  && ( result[result.Len() - 1] == wxT( '.' )
205  || result[result.Len() - 1] == wxT( ',' )
206  || (result[result.Len() - 1] >= wxT( '0' )
207  && result[result.Len() - 1] <= wxT( '9' ) ) ) )
208  {
209  result += aDefaultMeasurementUnit;
210  }
211 
212  return result;
213 }
214 
215 
216 int StrToInt1Units( const wxString& aStr )
217 {
218  double num, precision = 10;
219 
220  aStr.ToDouble( &num );
221  return KiROUND( num * precision );
222 }
223 
224 
225 wxString ValidateName( wxString aName )
226 {
227  aName.Replace( wxT( " " ), wxT( "_" ) );
228 
229  return aName;
230 }
231 
232 
233 wxString ValidateReference( wxString aRef )
234 {
235  wxRegEx reRef;
236  reRef.Compile( wxT( "^[[:digit:]][[:digit:]]*$" ) );
237 
238  if( reRef.Matches( aRef ) )
239  aRef.Prepend( wxT( '.' ) );
240 
241  return aRef;
242 }
243 
244 
245 void SetWidth( wxString aStr,
246  const wxString& aDefaultMeasurementUnit,
247  int* aWidth,
248  const wxString& aActualConversion )
249 {
251  aDefaultMeasurementUnit ), wxT( ' ' ),
252  aActualConversion );
253 }
254 
255 
256 void SetHeight( wxString aStr,
257  const wxString& aDefaultMeasurementUnit,
258  int* aHeight,
259  const wxString& aActualConversion )
260 {
261  *aHeight = StrToIntUnits( GetAndCutWordWithMeasureUnits( &aStr,
262  aDefaultMeasurementUnit ), wxT( ' ' ),
263  aActualConversion );
264 }
265 
266 
267 void SetPosition( wxString aStr,
268  const wxString& aDefaultMeasurementUnit,
269  int* aX,
270  int* aY,
271  const wxString& aActualConversion )
272 {
274  aDefaultMeasurementUnit ), wxT( 'X' ),
275  aActualConversion );
277  aDefaultMeasurementUnit ), wxT( 'Y' ),
278  aActualConversion );
279 }
280 
281 
282 void SetDoublePrecisionPosition( wxString aStr,
283  const wxString& aDefaultMeasurementUnit,
284  double* aX,
285  double* aY,
286  const wxString& aActualConversion )
287 {
289  aDefaultMeasurementUnit ), wxT( 'X' ),
290  aActualConversion );
292  aDefaultMeasurementUnit ), wxT( 'Y' ),
293  aActualConversion );
294 }
295 
296 
297 TTEXT_JUSTIFY GetJustifyIdentificator( const wxString& aJustify )
298 {
299  TTEXT_JUSTIFY id;
300 
301  if( aJustify == wxT( "LowerCenter" ) )
302  id = LowerCenter;
303  else if( aJustify == wxT( "LowerRight" ) )
304  id = LowerRight;
305  else if( aJustify == wxT( "UpperLeft" ) )
306  id = UpperLeft;
307  else if( aJustify == wxT( "UpperCenter" ) )
308  id = UpperCenter;
309  else if( aJustify == wxT( "UpperRight" ) )
310  id = UpperRight;
311  else if( aJustify == wxT( "Left" ) )
312  id = Left;
313  else if( aJustify == wxT( "Center" ) )
314  id = Center;
315  else if( aJustify == wxT( "Right" ) )
316  id = Right;
317  else
318  id = LowerLeft;
319 
320  return id;
321 }
322 
323 
325  TTEXTVALUE* aTextValue,
326  const wxString& aDefaultMeasurementUnit,
327  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(),
336  aDefaultMeasurementUnit,
337  &aTextValue->textPositionX,
338  &aTextValue->textPositionY,
339  aActualConversion );
340 
341  tNode = FindNode( aNode, wxT( "rotation" ) );
342 
343  if( tNode )
344  {
345  str = tNode->GetNodeContent();
346  str.Trim( false );
347  aTextValue->textRotation = StrToInt1Units( str );
348  }
349  else
350  {
351  aTextValue->textRotation = 0;
352  }
353 
354  str = FindNodeGetContent( aNode, wxT( "isVisible" ) );
355 
356  if( str == wxT( "True" ) )
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 == wxT( "True" ) )
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 
378 void SetFontProperty( XNODE* aNode,
379  TTEXTVALUE* aTextValue,
380  const wxString& aDefaultMeasurementUnit,
381  const wxString& aActualConversion )
382 {
383  wxString n, propValue;
384 
385  aNode->GetAttribute( wxT( "Name" ), &n );
386 
387  while( aNode->GetName() != wxT( "www.lura.sk" ) )
388  aNode = aNode->GetParent();
389 
390  aNode = FindNode( aNode, wxT( "library" ) );
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  if( ( aTextValue->isTrueType && ( fontType != wxT( "TrueType" ) ) ) ||
416  ( !aTextValue->isTrueType && ( fontType != wxT( "Stroke" ) ) ) )
417  aNode = aNode->GetNext();
418 
419  if( aNode )
420  {
421  if( aTextValue->isTrueType )
422  {
423  propValue = FindNodeGetContent( aNode, wxT( "fontItalic" ) );
424  aTextValue->isItalic = ( propValue == wxT( "True" ) );
425 
426  propValue = FindNodeGetContent( aNode, wxT( "fontWeight" ) );
427  if( propValue != wxEmptyString )
428  {
429  long fontWeight;
430 
431  propValue.ToLong( &fontWeight );
432  aTextValue->isBold = ( fontWeight >= TRUETYPE_BOLD_MIN_WEIGHT );
433  }
434  }
435 
436  XNODE* lNode;
437 
438  lNode = FindNode( aNode, wxT( "fontHeight" ) );
439  if( lNode )
440  SetHeight( lNode->GetNodeContent(), aDefaultMeasurementUnit,
441  &aTextValue->textHeight, aActualConversion );
442 
443  if( aTextValue->isTrueType )
444  {
445  aTextValue->textstrokeWidth = TRUETYPE_THICK_PER_HEIGHT * aTextValue->textHeight;
446  if( aTextValue->isBold )
448  }
449  else
450  {
451  lNode = FindNode( aNode, wxT( "strokeWidth" ) );
452  if( lNode )
453  SetWidth( lNode->GetNodeContent(), aDefaultMeasurementUnit,
454  &aTextValue->textstrokeWidth, aActualConversion );
455  }
456  }
457  }
458 }
459 
460 
461 void 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 ||
521  aValue->justify == Left ||
522  aValue->justify == UpperLeft )
523  posX += cl * cm;
524  else if( aValue->justify == LowerRight ||
525  aValue->justify == Right ||
526  aValue->justify == UpperRight )
527  posX -= cl * cm;
528 
529  if( aValue->justify == LowerLeft ||
530  aValue->justify == LowerCenter ||
531  aValue->justify == LowerRight )
532  posY -= ch;
533  else if( aValue->justify == UpperLeft ||
534  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 NULL;
572 }
573 
574 wxString 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 void InitTTextValue( TTEXTVALUE* aTextValue )
591 {
592  aTextValue->text = wxEmptyString;
593  aTextValue->textPositionX = 0;
594  aTextValue->textPositionY = 0;
595  aTextValue->textRotation = 0;
596  aTextValue->textHeight = 0;
597  aTextValue->textstrokeWidth = 0;
598  aTextValue->textIsVisible = 0;
599  aTextValue->mirror = 0;
600  aTextValue->textUnit = 0;
601  aTextValue->correctedPositionX = 0;
602  aTextValue->correctedPositionY = 0;
603  aTextValue->justify = LowerLeft;
604  aTextValue->isBold = false;
605  aTextValue->isItalic = false;
606  aTextValue->isTrueType = false;
607 }
608 
609 } // namespace PCAD2KICAD
const long TRUETYPE_BOLD_MIN_WEIGHT
wxString GetWord(wxString *aStr)
void SetFontProperty(XNODE *aNode, TTEXTVALUE *aTextValue, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion)
void SetPosition(wxString aStr, const wxString &aDefaultMeasurementUnit, int *aX, int *aY, 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 SetWidth(wxString aStr, const wxString &aDefaultMeasurementUnit, int *aWidth, const wxString &aActualConversion)
void SetHeight(wxString aStr, const wxString &aDefaultMeasurementUnit, int *aHeight, const wxString &aActualConversion)
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:208
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:112
wxString ValidateName(wxString aName)
int CalculateTextLengthSize(TTEXTVALUE *aText)
XNODE * GetChildren() const
Definition: xnode.h:63
#define NULL
const double STROKE_WIDTH_TO_SIZE
XNODE * GetParent() const
Definition: xnode.h:73
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)
wxString ValidateReference(wxString aRef)
const double STROKE_HEIGHT_TO_SIZE
void SetDoublePrecisionPosition(wxString aStr, const wxString &aDefaultMeasurementUnit, double *aX, double *aY, const wxString &aActualConversion)
int StrToIntUnits(const wxString &aStr, char aAxe, const wxString &aActualConversion)
XNODE holds 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:68
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:201
void CorrectTextPosition(TTEXTVALUE *aValue)
TTEXT_JUSTIFY GetJustifyIdentificator(const wxString &aJustify)
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:68
void InitTTextValue(TTEXTVALUE *aTextValue)
The common library.
void SetTextSizeFromStrokeFontHeight(EDA_TEXT *aText, int aTextHeight)
XNODE * FindPinMap(XNODE *aNode)
int StrToInt1Units(const wxString &aStr)