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/config.h>
32 #include <wx/regex.h>
33 
34 #include <common.h>
35 #include <convert_to_biu.h>
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  // TODO: Is the following commented string necessary?
221  // if (pos(',',s)>0) then DecimalSeparator:=',' else DecimalSeparator:='.';
222  aStr.ToDouble( &num );
223  return KiROUND( num * precision );
224 }
225 
226 
227 wxString ValidateName( wxString aName )
228 {
229  aName.Replace( wxT( " " ), wxT( "_" ) );
230 
231  return aName;
232 }
233 
234 
235 wxString ValidateReference( wxString aRef )
236 {
237  wxRegEx reRef;
238  reRef.Compile( wxT( "^[[:digit:]][[:digit:]]*$" ) );
239 
240  if( reRef.Matches( aRef ) )
241  aRef.Prepend( wxT( '.' ) );
242 
243  return aRef;
244 }
245 
246 
247 void SetWidth( wxString aStr,
248  const wxString& aDefaultMeasurementUnit,
249  int* aWidth,
250  const wxString& aActualConversion )
251 {
253  aDefaultMeasurementUnit ), wxT( ' ' ),
254  aActualConversion );
255 }
256 
257 
258 void SetHeight( wxString aStr,
259  const wxString& aDefaultMeasurementUnit,
260  int* aHeight,
261  const wxString& aActualConversion )
262 {
263  *aHeight = StrToIntUnits( GetAndCutWordWithMeasureUnits( &aStr,
264  aDefaultMeasurementUnit ), wxT( ' ' ),
265  aActualConversion );
266 }
267 
268 
269 void SetPosition( wxString aStr,
270  const wxString& aDefaultMeasurementUnit,
271  int* aX,
272  int* aY,
273  const wxString& aActualConversion )
274 {
276  aDefaultMeasurementUnit ), wxT( 'X' ),
277  aActualConversion );
279  aDefaultMeasurementUnit ), wxT( 'Y' ),
280  aActualConversion );
281 }
282 
283 
284 void SetDoublePrecisionPosition( wxString aStr,
285  const wxString& aDefaultMeasurementUnit,
286  double* aX,
287  double* aY,
288  const wxString& aActualConversion )
289 {
291  aDefaultMeasurementUnit ), wxT( 'X' ),
292  aActualConversion );
294  aDefaultMeasurementUnit ), wxT( 'Y' ),
295  aActualConversion );
296 }
297 
298 
299 TTEXT_JUSTIFY GetJustifyIdentificator( const wxString& aJustify )
300 {
301  TTEXT_JUSTIFY id;
302 
303  if( aJustify == wxT( "LowerCenter" ) )
304  id = LowerCenter;
305  else if( aJustify == wxT( "LowerRight" ) )
306  id = LowerRight;
307  else if( aJustify == wxT( "UpperLeft" ) )
308  id = UpperLeft;
309  else if( aJustify == wxT( "UpperCenter" ) )
310  id = UpperCenter;
311  else if( aJustify == wxT( "UpperRight" ) )
312  id = UpperRight;
313  else if( aJustify == wxT( "Left" ) )
314  id = Left;
315  else if( aJustify == wxT( "Center" ) )
316  id = Center;
317  else if( aJustify == wxT( "Right" ) )
318  id = Right;
319  else
320  id = LowerLeft;
321 
322  return id;
323 }
324 
325 
327  TTEXTVALUE* aTextValue,
328  const wxString& aDefaultMeasurementUnit,
329  const wxString& aActualConversion )
330 {
331  XNODE* tNode;
332  wxString str;
333 
334  tNode = FindNode( aNode, wxT( "pt" ) );
335 
336  if( tNode )
337  SetPosition( tNode->GetNodeContent(),
338  aDefaultMeasurementUnit,
339  &aTextValue->textPositionX,
340  &aTextValue->textPositionY,
341  aActualConversion );
342 
343  tNode = FindNode( aNode, wxT( "rotation" ) );
344 
345  if( tNode )
346  {
347  str = tNode->GetNodeContent();
348  str.Trim( false );
349  aTextValue->textRotation = StrToInt1Units( str );
350  }
351  else
352  {
353  aTextValue->textRotation = 0;
354  }
355 
356  str = FindNodeGetContent( aNode, wxT( "isVisible" ) );
357 
358  if( str == wxT( "True" ) )
359  aTextValue->textIsVisible = 1;
360  else
361  aTextValue->textIsVisible = 0;
362 
363  str = FindNodeGetContent( aNode, wxT( "justify" ) );
364  aTextValue->justify = GetJustifyIdentificator( str );
365 
366  str = FindNodeGetContent( aNode, wxT( "isFlipped" ) );
367 
368  if( str == wxT( "True" ) )
369  aTextValue->mirror = 1;
370  else
371  aTextValue->mirror = 0;
372 
373  tNode = FindNode( aNode, wxT( "textStyleRef" ) );
374 
375  if( tNode )
376  SetFontProperty( tNode, aTextValue, aDefaultMeasurementUnit, aActualConversion );
377 }
378 
379 
380 void SetFontProperty( XNODE* aNode,
381  TTEXTVALUE* aTextValue,
382  const wxString& aDefaultMeasurementUnit,
383  const wxString& aActualConversion )
384 {
385  wxString n, propValue;
386 
387  aNode->GetAttribute( wxT( "Name" ), &n );
388 
389  while( aNode->GetName() != wxT( "www.lura.sk" ) )
390  aNode = aNode->GetParent();
391 
392  aNode = FindNode( aNode, wxT( "library" ) );
393  if( aNode )
394  aNode = FindNode( aNode, wxT( "textStyleDef" ) );
395 
396  while( aNode )
397  {
398  aNode->GetAttribute( wxT( "Name" ), &propValue );
399  propValue.Trim( false );
400  propValue.Trim( true );
401 
402  if( propValue == n )
403  break;
404 
405  aNode = aNode->GetNext();
406  }
407 
408  if( aNode )
409  {
410  wxString fontType;
411 
412  propValue = FindNodeGetContent( aNode, wxT( "textStyleDisplayTType" ) );
413  aTextValue->isTrueType = ( propValue == wxT( "True" ) );
414 
415  aNode = FindNode( aNode, wxT( "font" ) );
416  fontType = FindNodeGetContent( aNode, wxT( "fontType" ) );
417  if( ( aTextValue->isTrueType && ( fontType != wxT( "TrueType" ) ) ) ||
418  ( !aTextValue->isTrueType && ( fontType != wxT( "Stroke" ) ) ) )
419  aNode = aNode->GetNext();
420 
421  if( aNode )
422  {
423  if( aTextValue->isTrueType )
424  {
425  propValue = FindNodeGetContent( aNode, wxT( "fontItalic" ) );
426  aTextValue->isItalic = ( propValue == wxT( "True" ) );
427 
428  propValue = FindNodeGetContent( aNode, wxT( "fontWeight" ) );
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  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  if( aTextValue->isBold )
450  }
451  else
452  {
453  lNode = FindNode( aNode, wxT( "strokeWidth" ) );
454  if( lNode )
455  SetWidth( lNode->GetNodeContent(), aDefaultMeasurementUnit,
456  &aTextValue->textstrokeWidth, aActualConversion );
457  }
458  }
459  }
460 }
461 
462 
463 void SetTextJustify( EDA_TEXT* aText, TTEXT_JUSTIFY aJustify )
464 {
465  switch( aJustify )
466  {
467  case LowerLeft:
470  break;
471  case LowerCenter:
474  break;
475  case LowerRight:
478  break;
479  case UpperLeft:
482  break;
483  case UpperCenter:
486  break;
487  case UpperRight:
490  break;
491  case Left:
494  break;
495  case Center:
498  break;
499  case Right:
502  break;
503  }
504 }
505 
506 
508 {
509  return KiROUND( (double) aText->text.Len() *
510  (double) aText->textHeight * TEXT_WIDTH_TO_SIZE_AVERAGE );
511 }
512 
513 
515 {
516  int cm = aValue->mirror ? -1 : 1;
517  int cl = KiROUND( (double) CalculateTextLengthSize( aValue ) / 2.0 );
518  int ch = KiROUND( (double) aValue->textHeight / 2.0 );
519  int posX = 0;
520  int posY = 0;
521 
522  if( aValue->justify == LowerLeft ||
523  aValue->justify == Left ||
524  aValue->justify == UpperLeft )
525  posX += cl * cm;
526  else if( aValue->justify == LowerRight ||
527  aValue->justify == Right ||
528  aValue->justify == UpperRight )
529  posX -= cl * cm;
530 
531  if( aValue->justify == LowerLeft ||
532  aValue->justify == LowerCenter ||
533  aValue->justify == LowerRight )
534  posY -= ch;
535  else if( aValue->justify == UpperLeft ||
536  aValue->justify == UpperCenter ||
537  aValue->justify == UpperRight )
538  posY += ch;
539 
540  RotatePoint( &posX, &posY, aValue->textRotation );
541 
542  aValue->correctedPositionX = aValue->textPositionX + posX;
543  aValue->correctedPositionY = aValue->textPositionY + posY;
544 }
545 
546 
547 void SetTextSizeFromStrokeFontHeight( EDA_TEXT* aText, int aTextHeight )
548 {
549  aText->SetTextSize( wxSize( KiROUND( aTextHeight * STROKE_WIDTH_TO_SIZE ),
550  KiROUND( aTextHeight * STROKE_HEIGHT_TO_SIZE ) ) );
551 }
552 
553 
554 void SetTextSizeFromTrueTypeFontHeight( EDA_TEXT* aText, int aTextHeight )
555 {
556  aText->SetTextSize( wxSize( KiROUND( aTextHeight * TRUETYPE_WIDTH_TO_SIZE ),
557  KiROUND( aTextHeight * TRUETYPE_HEIGHT_TO_SIZE ) ) );
558 }
559 
560 
561 XNODE* FindNode( XNODE* aChild, const wxString& aTag )
562 {
563  aChild = aChild->GetChildren();
564 
565  while( aChild )
566  {
567  if( aChild->GetName() == aTag )
568  return aChild;
569 
570  aChild = aChild->GetNext();
571  }
572 
573  return NULL;
574 }
575 
576 wxString FindNodeGetContent( XNODE* aChild, const wxString& aTag )
577 {
578  wxString str = wxEmptyString;
579 
580  aChild = FindNode( aChild, aTag );
581 
582  if( aChild )
583  {
584  str = aChild->GetNodeContent();
585  str.Trim( false );
586  str.Trim( true );
587  }
588 
589  return str;
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 GetWord(wxString *aStr)
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:107
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:212
const double TRUETYPE_WIDTH_TO_SIZE
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
void SetTextSizeFromTrueTypeFontHeight(EDA_TEXT *aText, int aTextHeight)
XNODE * GetParent() const
Definition: xnode.h:73
Class EDA_TEXT is a mix-in class (via multiple inheritance) that handles texts such as labels...
Definition: eda_text.h:112
wxString ValidateName(wxString aName)
int CalculateTextLengthSize(TTEXTVALUE *aText)
const double STROKE_WIDTH_TO_SIZE
wxString FindNodeGetContent(XNODE *aChild, const wxString &aTag)
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:192
void SetTextParameters(XNODE *aNode, TTEXTVALUE *aTextValue, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion)
XNODE * GetChildren() const
Definition: xnode.h:63
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)
Class 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
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:191
void CorrectTextPosition(TTEXTVALUE *aValue)
TTEXT_JUSTIFY GetJustifyIdentificator(const wxString &aJustify)
XNODE * FindNode(XNODE *aChild, const wxString &aTag)
void InitTTextValue(TTEXTVALUE *aTextValue)
The common library.
void SetTextSizeFromStrokeFontHeight(EDA_TEXT *aText, int aTextHeight)
XNODE * GetNext() const
Definition: xnode.h:68
XNODE * FindPinMap(XNODE *aNode)
int StrToInt1Units(const wxString &aStr)