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 
33 #include <common.h>
34 #include <convert_to_biu.h>
35 
36 #include <pcad2kicad_common.h>
37 
38 namespace PCAD2KICAD {
39 
40 // PCAD stroke font average ratio of width to size
41 const double TEXT_WIDTH_TO_SIZE_AVERAGE = 0.79;
42 // PCAD proportions of stroke font
43 const double TEXT_HEIGHT_TO_SIZE = 0.656;
44 const double TEXT_WIDTH_TO_SIZE = 0.656;
45 
46 wxString GetWord( wxString* aStr )
47 {
48  wxString result = wxEmptyString;
49 
50  *aStr = aStr->Trim( false );
51 
52  if( aStr->Len() == 0 )
53  return result;
54 
55  if( (*aStr)[0] == wxT( '"' ) )
56  {
57  result += (*aStr)[0];
58  *aStr = aStr->Mid( 1 ); // remove Frot apostrofe
59 
60  while( aStr->Len() > 0 && (*aStr)[0] != wxT( '"' ) )
61  {
62  result += (*aStr)[0];
63  *aStr = aStr->Mid( 1 );
64  }
65 
66  if( aStr->Len() > 0 && (*aStr)[0] == wxT( '"' ) )
67  {
68  result += (*aStr)[0];
69  *aStr = aStr->Mid( 1 ); // remove ending apostrophe
70  }
71  }
72  else
73  {
74  while( aStr->Len() > 0
75  && !( (*aStr)[0] == wxT( ' ' )
76  || (*aStr)[0] == wxT( '(' )
77  || (*aStr)[0] == wxT( ')' ) ) )
78  {
79  result += (*aStr)[0];
80  *aStr = aStr->Mid( 1 );
81  }
82  }
83 
84  result.Trim( true );
85  result.Trim( false );
86 
87  return result;
88 }
89 
90 
92 {
93  XNODE* result, * lNode;
94 
95  result = NULL;
96  lNode = FindNode( aNode, wxT( "attachedPattern" ) );
97 
98  if( lNode )
99  result = FindNode( lNode, wxT( "padPinMap" ) );
100 
101  return result;
102 }
103 
104 
105 double StrToDoublePrecisionUnits( wxString aStr, char aAxe, wxString aActualConversion )
106 {
107  wxString ls;
108  double i;
109  char u;
110 
111  ls = aStr;
112  ls.Trim( true );
113  ls.Trim( false );
114 
115  if( ls.Len() > 0 )
116  {
117  u = ls[ls.Len() - 1];
118 
119  while( ls.Len() > 0
120  && !( ls[ls.Len() - 1] == wxT( '.' )
121  || ls[ls.Len() - 1] == wxT( ',' )
122  || (ls[ls.Len() - 1] >= wxT( '0' ) && ls[ls.Len() - 1] <= wxT( '9' ) ) ) )
123  {
124  ls = ls.Left( ls.Len() - 1 );
125  }
126 
127  while( ls.Len() > 0
128  && !( ls[0] == wxT( '-' )
129  || ls[0] == wxT( '+' )
130  || ls[0] == wxT( '.' )
131  || ls[0] == wxT( ',' )
132  || (ls[0] >= wxT( '0' ) && ls[0] <= wxT( '9' ) ) ) )
133  {
134  ls = ls.Mid( 1 );
135  }
136 
137  if( u == wxT( 'm' ) )
138  {
139  ls.ToDouble( &i );
140 #ifdef PCAD2KICAD_SCALE_SCH_TO_INCH_GRID
141  if( aActualConversion == wxT( "SCH" )
142  || aActualConversion == wxT( "SCHLIB" ) )
143  i = i * (0.0254 / 0.025);
144 #endif
145  i = Millimeter2iu( i );
146  }
147  else
148  {
149  ls.ToDouble( &i );
150  i = Mils2iu( i );
151  }
152  }
153  else
154  i = 0.0;
155 
156  if( ( aActualConversion == wxT( "PCB" ) || aActualConversion == wxT( "SCH" ) )
157  && aAxe == wxT( 'Y' ) )
158  return -i;
159  else
160  return i; // Y axe is mirrored compared to P-Cad
161 }
162 
163 
164 int StrToIntUnits( wxString aStr, char aAxe, wxString aActualConversion )
165 {
166  return KiROUND( StrToDoublePrecisionUnits( aStr, aAxe, aActualConversion ) );
167 }
168 
169 
170 wxString GetAndCutWordWithMeasureUnits( wxString* aStr, wxString aDefaultMeasurementUnit )
171 {
172  wxString result;
173 
174  aStr->Trim( false );
175  result = wxEmptyString;
176 
177  // value
178  while( aStr->Len() > 0 && (*aStr)[0] != wxT( ' ' ) )
179  {
180  result += (*aStr)[0];
181  *aStr = aStr->Mid( 1 );
182  }
183 
184  aStr->Trim( false );
185 
186  // if there is also measurement unit
187  while( aStr->Len() > 0
188  && ( ( (*aStr)[0] >= wxT( 'a' ) && (*aStr)[0] <= wxT( 'z' ) )
189  || ( (*aStr)[0] >= wxT( 'A' ) && (*aStr)[0] <= wxT( 'Z' ) ) ) )
190  {
191  result += (*aStr)[0];
192  *aStr = aStr->Mid( 1 );
193  }
194 
195  // and if not, add default....
196  if( result.Len() > 0
197  && ( result[result.Len() - 1] == wxT( '.' )
198  || result[result.Len() - 1] == wxT( ',' )
199  || (result[result.Len() - 1] >= wxT( '0' )
200  && result[result.Len() - 1] <= wxT( '9' ) ) ) )
201  {
202  result += aDefaultMeasurementUnit;
203  }
204 
205  return result;
206 }
207 
208 
209 int StrToInt1Units( wxString aStr )
210 {
211  double num, precision = 10;
212 
213  // TODO: Is the following commented string necessary?
214  // if (pos(',',s)>0) then DecimalSeparator:=',' else DecimalSeparator:='.';
215  aStr.ToDouble( &num );
216  return KiROUND( num * precision );
217 }
218 
219 
220 wxString ValidateName( wxString aName )
221 {
222  aName.Replace( wxT( " " ), wxT( "_" ) );
223 
224  return aName;
225 }
226 
227 
228 void SetWidth( wxString aStr,
229  wxString aDefaultMeasurementUnit,
230  int* aWidth,
231  wxString aActualConversion )
232 {
234  aDefaultMeasurementUnit ), wxT( ' ' ),
235  aActualConversion );
236 }
237 
238 
239 void SetHeight( wxString aStr,
240  wxString aDefaultMeasurementUnit,
241  int* aHeight,
242  wxString aActualConversion )
243 {
244  *aHeight = StrToIntUnits( GetAndCutWordWithMeasureUnits( &aStr,
245  aDefaultMeasurementUnit ), wxT( ' ' ),
246  aActualConversion );
247 }
248 
249 
250 void SetPosition( wxString aStr,
251  wxString aDefaultMeasurementUnit,
252  int* aX,
253  int* aY,
254  wxString aActualConversion )
255 {
257  aDefaultMeasurementUnit ), wxT( 'X' ),
258  aActualConversion );
260  aDefaultMeasurementUnit ), wxT( 'Y' ),
261  aActualConversion );
262 }
263 
264 
265 void SetDoublePrecisionPosition( wxString aStr,
266  wxString aDefaultMeasurementUnit,
267  double* aX,
268  double* aY,
269  wxString aActualConversion )
270 {
272  aDefaultMeasurementUnit ), wxT( 'X' ),
273  aActualConversion );
275  aDefaultMeasurementUnit ), wxT( 'Y' ),
276  aActualConversion );
277 }
278 
280 {
281  TTEXT_JUSTIFY id;
282 
283  if( aJustify == wxT( "LowerCenter" ) )
284  id = LowerCenter;
285  else if( aJustify == wxT( "LowerRight" ) )
286  id = LowerRight;
287  else if( aJustify == wxT( "UpperLeft" ) )
288  id = UpperLeft;
289  else if( aJustify == wxT( "UpperCenter" ) )
290  id = UpperCenter;
291  else if( aJustify == wxT( "UpperRight" ) )
292  id = UpperRight;
293  else if( aJustify == wxT( "Left" ) )
294  id = Left;
295  else if( aJustify == wxT( "Center" ) )
296  id = Center;
297  else if( aJustify == wxT( "Right" ) )
298  id = Right;
299  else
300  id = LowerLeft;
301 
302  return id;
303 }
304 
306  TTEXTVALUE* aTextValue,
307  wxString aDefaultMeasurementUnit,
308  wxString aActualConversion )
309 {
310  XNODE* tNode;
311  wxString str;
312 
313  tNode = FindNode( aNode, wxT( "pt" ) );
314 
315  if( tNode )
316  SetPosition( tNode->GetNodeContent(),
317  aDefaultMeasurementUnit,
318  &aTextValue->textPositionX,
319  &aTextValue->textPositionY,
320  aActualConversion );
321 
322  tNode = FindNode( aNode, wxT( "rotation" ) );
323 
324  if( tNode )
325  {
326  str = tNode->GetNodeContent();
327  str.Trim( false );
328  aTextValue->textRotation = StrToInt1Units( str );
329  }
330 
331  str = FindNodeGetContent( aNode, wxT( "isVisible" ) );
332 
333  if( str == wxT( "True" ) )
334  aTextValue->textIsVisible = 1;
335  else if( str == wxT( "False" ) )
336  aTextValue->textIsVisible = 0;
337 
338  str = FindNodeGetContent( aNode, wxT( "justify" ) );
339  aTextValue->justify = GetJustifyIdentificator( str );
340 
341  str = FindNodeGetContent( aNode, wxT( "isFlipped" ) );
342 
343  if( str == wxT( "True" ) )
344  aTextValue->mirror = 1;
345 
346  tNode = FindNode( aNode, wxT( "textStyleRef" ) );
347 
348  if( tNode )
349  SetFontProperty( tNode, aTextValue, aDefaultMeasurementUnit, aActualConversion );
350 }
351 
352 
353 void SetFontProperty( XNODE* aNode,
354  TTEXTVALUE* aTextValue,
355  wxString aDefaultMeasurementUnit,
356  wxString aActualConversion )
357 {
358  wxString n, propValue;
359 
360  aNode->GetAttribute( wxT( "Name" ), &n );
361 
362  while( aNode->GetName() != wxT( "www.lura.sk" ) )
363  aNode = aNode->GetParent();
364 
365  aNode = FindNode( aNode, wxT( "library" ) );
366 
367  if( aNode )
368  aNode = FindNode( aNode, wxT( "textStyleDef" ) );
369 
370  if( aNode )
371  {
372  while( true )
373  {
374  aNode->GetAttribute( wxT( "Name" ), &propValue );
375  propValue.Trim( false );
376  propValue.Trim( true );
377 
378  if( propValue == n )
379  break;
380 
381  aNode = aNode->GetNext();
382  }
383 
384  if( aNode )
385  {
386  aNode = FindNode( aNode, wxT( "font" ) );
387 
388  if( aNode )
389  {
390  if( FindNode( aNode, wxT( "fontHeight" ) ) )
391  // // SetWidth(iNode.ChildNodes.FindNode('fontHeight').Text,
392  // // DefaultMeasurementUnit,tv.TextHeight);
393  // Fixed By Lubo, 02/2008
394  SetHeight( FindNode( aNode, wxT(
395  "fontHeight" ) )->GetNodeContent(),
396  aDefaultMeasurementUnit, &aTextValue->textHeight,
397  aActualConversion );
398 
399  if( FindNode( aNode, wxT( "strokeWidth" ) ) )
400  SetWidth( FindNode( aNode, wxT(
401  "strokeWidth" ) )->GetNodeContent(),
402  aDefaultMeasurementUnit, &aTextValue->textstrokeWidth,
403  aActualConversion );
404  }
405  }
406  }
407 }
408 
409 void SetTextJustify( EDA_TEXT* aText, TTEXT_JUSTIFY aJustify )
410 {
411  switch( aJustify )
412  {
413  case LowerLeft:
416  break;
417  case LowerCenter:
420  break;
421  case LowerRight:
424  break;
425  case UpperLeft:
428  break;
429  case UpperCenter:
432  break;
433  case UpperRight:
436  break;
437  case Left:
440  break;
441  case Center:
444  break;
445  case Right:
448  break;
449  }
450 }
451 
453 {
454  return KiROUND( (double) aText->text.Len() *
455  (double) aText->textHeight * TEXT_WIDTH_TO_SIZE_AVERAGE );
456 }
457 
459 {
460  int cm = aValue->mirror ? -1 : 1;
461  // sizes of justify correction
462  int cl = KiROUND( (double) CalculateTextLengthSize( aValue ) / 2.0 );
463  int ch = KiROUND( (double) aValue->textHeight / 2.0 );
464 
465  aValue->correctedPositionX = aValue->textPositionX;
466  aValue->correctedPositionY = aValue->textPositionY;
467 
468  switch( aValue->textRotation )
469  {
470  case 0:
471  if( aValue->justify == LowerLeft ||
472  aValue->justify == Left ||
473  aValue->justify == UpperLeft )
474  aValue->correctedPositionX += cl * cm;
475  else if( aValue->justify == LowerRight ||
476  aValue->justify == Right ||
477  aValue->justify == UpperRight )
478  aValue->correctedPositionX -= cl * cm;
479 
480  if( aValue->justify == LowerLeft ||
481  aValue->justify == LowerCenter ||
482  aValue->justify == LowerRight )
483  aValue->correctedPositionY -= ch;
484  else if( aValue->justify == UpperLeft ||
485  aValue->justify == UpperCenter ||
486  aValue->justify == UpperRight )
487  aValue->correctedPositionY += ch;
488  break;
489  case 900:
490  if( aValue->justify == LowerLeft ||
491  aValue->justify == LowerCenter ||
492  aValue->justify == LowerRight )
493  aValue->correctedPositionX -= ch * cm;
494  else if( aValue->justify == UpperLeft ||
495  aValue->justify == UpperCenter ||
496  aValue->justify == UpperRight )
497  aValue->correctedPositionX += ch * cm;
498 
499  if( aValue->justify == LowerLeft ||
500  aValue->justify == Left ||
501  aValue->justify == UpperLeft )
502  aValue->correctedPositionY -= cl;
503  else if( aValue->justify == LowerRight ||
504  aValue->justify == Right ||
505  aValue->justify == UpperRight )
506  aValue->correctedPositionY += cl;
507  break;
508  case 1800:
509  if( aValue->justify == LowerLeft ||
510  aValue->justify == Left ||
511  aValue->justify == UpperLeft )
512  aValue->correctedPositionX -= cl * cm;
513  else if( aValue->justify == LowerRight ||
514  aValue->justify == Right ||
515  aValue->justify == UpperRight )
516  aValue->correctedPositionX += cl * cm;
517 
518  if( aValue->justify == LowerLeft ||
519  aValue->justify == LowerCenter ||
520  aValue->justify == LowerRight )
521  aValue->correctedPositionY += ch;
522  else if( aValue->justify == UpperLeft ||
523  aValue->justify == UpperCenter ||
524  aValue->justify == UpperRight )
525  aValue->correctedPositionY -= ch;
526  break;
527  case 2700:
528  if( aValue->justify == LowerLeft ||
529  aValue->justify == LowerCenter ||
530  aValue->justify == LowerRight )
531  aValue->correctedPositionX += ch * cm;
532  else if( aValue->justify == UpperLeft ||
533  aValue->justify == UpperCenter ||
534  aValue->justify == UpperRight )
535  aValue->correctedPositionX -= ch * cm;
536 
537  if( aValue->justify == LowerLeft ||
538  aValue->justify == Left ||
539  aValue->justify == UpperLeft )
540  aValue->correctedPositionY += cl;
541  else if( aValue->justify == LowerRight ||
542  aValue->justify == Right ||
543  aValue->justify == UpperRight )
544  aValue->correctedPositionY -= cl;
545  break;
546  default:
547  break;
548  }
549 }
550 
551 
552 void SetTextSizeFromStrokeFontHeight( EDA_TEXT* aText, int aTextHeight )
553 {
554  aText->SetTextSize( wxSize( KiROUND( aTextHeight * TEXT_WIDTH_TO_SIZE ),
555  KiROUND( aTextHeight * TEXT_HEIGHT_TO_SIZE ) ) );
556 }
557 
558 
559 XNODE* FindNode( XNODE* aChild, 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, 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 }
605 
606 } // namespace PCAD2KICAD
void SetWidth(wxString aStr, wxString aDefaultMeasurementUnit, int *aWidth, wxString aActualConversion)
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
int StrToInt1Units(wxString aStr)
const double TEXT_WIDTH_TO_SIZE_AVERAGE
TTEXT_JUSTIFY GetJustifyIdentificator(wxString aJustify)
double StrToDoublePrecisionUnits(wxString aStr, char aAxe, wxString aActualConversion)
wxString GetAndCutWordWithMeasureUnits(wxString *aStr, wxString aDefaultMeasurementUnit)
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:214
void SetTextParameters(XNODE *aNode, TTEXTVALUE *aTextValue, wxString aDefaultMeasurementUnit, wxString aActualConversion)
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:114
wxString FindNodeGetContent(XNODE *aChild, wxString aTag)
wxString ValidateName(wxString aName)
int CalculateTextLengthSize(TTEXTVALUE *aText)
void SetHeight(wxString aStr, wxString aDefaultMeasurementUnit, int *aHeight, wxString aActualConversion)
const double TEXT_HEIGHT_TO_SIZE
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:194
XNODE * GetChildren() const
Definition: xnode.h:63
void SetPosition(wxString aStr, wxString aDefaultMeasurementUnit, int *aX, int *aY, wxString aActualConversion)
void SetFontProperty(XNODE *aNode, TTEXTVALUE *aTextValue, wxString aDefaultMeasurementUnit, wxString aActualConversion)
const double TEXT_WIDTH_TO_SIZE
Class XNODE holds an XML or S-expression element.
Definition: xnode.h:43
void SetTextJustify(EDA_TEXT *aText, TTEXT_JUSTIFY aJustify)
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:193
int StrToIntUnits(wxString aStr, char aAxe, wxString aActualConversion)
void CorrectTextPosition(TTEXTVALUE *aValue)
void InitTTextValue(TTEXTVALUE *aTextValue)
The common library.
XNODE * FindNode(XNODE *aChild, wxString aTag)
void SetTextSizeFromStrokeFontHeight(EDA_TEXT *aText, int aTextHeight)
XNODE * GetNext() const
Definition: xnode.h:68
XNODE * FindPinMap(XNODE *aNode)
void SetDoublePrecisionPosition(wxString aStr, wxString aDefaultMeasurementUnit, double *aX, double *aY, wxString aActualConversion)