You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2266 lines
58 KiB

14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
  1. /**
  2. * @file item_io.cpp
  3. * @brief Routines for reading and saving of structures in ASCII file common to Pcbnew and CvPcb.
  4. * This is migrationary and temporary while we move the IO_MGR.
  5. */
  6. #include <fctsys.h>
  7. #include <confirm.h>
  8. #include <kicad_string.h>
  9. #include <build_version.h>
  10. #include <wxPcbStruct.h>
  11. #include <richio.h>
  12. #include <macros.h>
  13. #include <pcbcommon.h>
  14. #include <zones.h>
  15. #ifdef CVPCB
  16. #include <cvpcb.h>
  17. #endif
  18. #include <config.h>
  19. #include <class_board.h>
  20. #include <class_module.h>
  21. #include <class_track.h>
  22. #include <class_pcb_text.h>
  23. #include <class_zone.h>
  24. #include <class_dimension.h>
  25. #include <class_drawsegment.h>
  26. #include <class_mire.h>
  27. #include <pcbnew.h>
  28. #include <pcbnew_id.h>
  29. #include <autorout.h>
  30. #include <3d_struct.h>
  31. #include <trigo.h>
  32. #include <class_edge_mod.h>
  33. #include <pcbnew.h>
  34. #include <drawtxt.h>
  35. #define MAX_WIDTH 10000 // Thickness (in 1 / 10000 ") of maximum reasonable features, text...
  36. #if 1 || !defined(USE_NEW_PCBNEW_SAVE)
  37. bool BOARD::Save( FILE* aFile ) const
  38. {
  39. bool rc = false;
  40. BOARD_ITEM* item;
  41. // save the nets
  42. for( unsigned ii = 0; ii < GetNetCount(); ii++ )
  43. if( !FindNet( ii )->Save( aFile ) )
  44. goto out;
  45. // Saved nets do not include netclass names, so save netclasses after nets.
  46. m_NetClasses.Save( aFile );
  47. // save the modules
  48. for( item = m_Modules; item; item = item->Next() )
  49. if( !item->Save( aFile ) )
  50. goto out;
  51. for( item = m_Drawings; item; item = item->Next() )
  52. {
  53. switch( item->Type() )
  54. {
  55. case PCB_TEXT_T:
  56. case PCB_LINE_T:
  57. case PCB_TARGET_T:
  58. case PCB_DIMENSION_T:
  59. if( !item->Save( aFile ) )
  60. goto out;
  61. break;
  62. default:
  63. // future: throw exception here
  64. #if defined(DEBUG)
  65. printf( "BOARD::Save() ignoring m_Drawings type %d\n", item->Type() );
  66. #endif
  67. break;
  68. }
  69. }
  70. // do not save MARKER_PCBs, they can be regenerated easily
  71. // save the tracks & vias
  72. fprintf( aFile, "$TRACK\n" );
  73. for( item = m_Track; item; item = item->Next() )
  74. {
  75. if( !item->Save( aFile ) )
  76. goto out;
  77. }
  78. fprintf( aFile, "$EndTRACK\n" );
  79. // save the zones
  80. fprintf( aFile, "$ZONE\n" );
  81. for( item = m_Zone; item; item = item->Next() )
  82. {
  83. if( !item->Save( aFile ) )
  84. goto out;
  85. }
  86. fprintf( aFile, "$EndZONE\n" );
  87. // save the zone edges
  88. for( unsigned ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
  89. {
  90. ZONE_CONTAINER* edge_zone = m_ZoneDescriptorList[ii];
  91. edge_zone->Save( aFile );
  92. }
  93. if( fprintf( aFile, "$EndBOARD\n" ) != sizeof("$EndBOARD\n") - 1 )
  94. goto out;
  95. rc = true; // wrote all OK
  96. out:
  97. return rc;
  98. }
  99. bool DRAWSEGMENT::Save( FILE* aFile ) const
  100. {
  101. if( fprintf( aFile, "$DRAWSEGMENT\n" ) != sizeof("$DRAWSEGMENT\n") - 1 )
  102. return false;
  103. fprintf( aFile, "Po %d %d %d %d %d %d\n",
  104. m_Shape,
  105. m_Start.x, m_Start.y,
  106. m_End.x, m_End.y, m_Width );
  107. if( m_Type != S_CURVE )
  108. {
  109. fprintf( aFile, "De %d %d %g %lX %X\n",
  110. m_Layer, m_Type, GetAngle(),
  111. m_TimeStamp, GetStatus() );
  112. }
  113. else
  114. {
  115. fprintf( aFile, "De %d %d %g %lX %X %d %d %d %d\n",
  116. m_Layer, m_Type, GetAngle(),
  117. m_TimeStamp, GetStatus(),
  118. m_BezierC1.x,m_BezierC1.y,
  119. m_BezierC2.x,m_BezierC2.y);
  120. }
  121. if( fprintf( aFile, "$EndDRAWSEGMENT\n" ) != sizeof("$EndDRAWSEGMENT\n") - 1 )
  122. return false;
  123. return true;
  124. }
  125. /** Note: the old name of class NETINFO_ITEM was EQUIPOT
  126. * so in Save (and read) functions, for compatibility, we use EQUIPOT as
  127. * keyword
  128. */
  129. bool NETINFO_ITEM::Save( FILE* aFile ) const
  130. {
  131. bool success = false;
  132. fprintf( aFile, "$EQUIPOT\n" );
  133. fprintf( aFile, "Na %d %s\n", GetNet(), EscapedUTF8( m_Netname ).c_str() );
  134. fprintf( aFile, "St %s\n", "~" );
  135. if( fprintf( aFile, "$EndEQUIPOT\n" ) != sizeof("$EndEQUIPOT\n") - 1 )
  136. goto out;
  137. success = true;
  138. out:
  139. return success;
  140. }
  141. bool PCB_TARGET::Save( FILE* aFile ) const
  142. {
  143. bool rc = false;
  144. if( fprintf( aFile, "$PCB_TARGET\n" ) != sizeof("$PCB_TARGET\n")-1 )
  145. goto out;
  146. fprintf( aFile, "Po %X %d %d %d %d %d %8.8lX\n",
  147. m_Shape, m_Layer,
  148. m_Pos.x, m_Pos.y,
  149. m_Size, m_Width, m_TimeStamp );
  150. if( fprintf( aFile, "$EndPCB_TARGET\n" ) != sizeof("$EndPCB_TARGET\n")-1 )
  151. goto out;
  152. rc = true;
  153. out:
  154. return rc;
  155. }
  156. bool ZONE_CONTAINER::Save( FILE* aFile ) const
  157. {
  158. unsigned item_pos;
  159. int ret;
  160. unsigned corners_count = m_Poly->corner.size();
  161. int outline_hatch;
  162. fprintf( aFile, "$CZONE_OUTLINE\n" );
  163. // Save the outline main info
  164. ret = fprintf( aFile, "ZInfo %8.8lX %d %s\n",
  165. m_TimeStamp, GetNet(),
  166. EscapedUTF8( m_Netname ).c_str() );
  167. if( ret < 3 )
  168. return false;
  169. // Save the outline layer info
  170. ret = fprintf( aFile, "ZLayer %d\n", m_Layer );
  171. if( ret < 1 )
  172. return false;
  173. // Save the outline aux info
  174. switch( m_Poly->GetHatchStyle() )
  175. {
  176. default:
  177. case CPolyLine::NO_HATCH:
  178. outline_hatch = 'N';
  179. break;
  180. case CPolyLine::DIAGONAL_EDGE:
  181. outline_hatch = 'E';
  182. break;
  183. case CPolyLine::DIAGONAL_FULL:
  184. outline_hatch = 'F';
  185. break;
  186. }
  187. ret = fprintf( aFile, "ZAux %d %c\n", corners_count, outline_hatch );
  188. if( ret < 2 )
  189. return false;
  190. if( GetPriority() > 0 )
  191. {
  192. ret = fprintf( aFile, "ZPriority %d\n", GetPriority() );
  193. if( ret < 1 )
  194. return false;
  195. }
  196. // Save pad option and clearance
  197. int padConnection;
  198. switch( m_PadConnection )
  199. {
  200. default:
  201. case PAD_IN_ZONE:
  202. padConnection = 'I';
  203. break;
  204. case THERMAL_PAD:
  205. padConnection = 'T';
  206. break;
  207. case PAD_NOT_IN_ZONE:
  208. padConnection = 'X';
  209. break;
  210. }
  211. ret = fprintf( aFile, "ZClearance %d %c\n", m_ZoneClearance, padConnection );
  212. if( ret < 2 )
  213. return false;
  214. ret = fprintf( aFile, "ZMinThickness %d\n", m_ZoneMinThickness );
  215. if( ret < 1 )
  216. return false;
  217. ret = fprintf( aFile,
  218. "ZOptions %d %d %c %d %d\n",
  219. m_FillMode,
  220. m_ArcToSegmentsCount,
  221. m_IsFilled ? 'S' : 'F',
  222. m_ThermalReliefGap,
  223. m_ThermalReliefCopperBridge );
  224. if( ret < 3 )
  225. return false;
  226. ret = fprintf( aFile,
  227. "ZSmoothing %d %d\n",
  228. cornerSmoothingType, cornerRadius );
  229. if( ret < 2 )
  230. return false;
  231. // Save the corner list
  232. for( item_pos = 0; item_pos < corners_count; item_pos++ )
  233. {
  234. ret = fprintf( aFile, "ZCorner %d %d %d\n",
  235. m_Poly->corner[item_pos].x, m_Poly->corner[item_pos].y,
  236. m_Poly->corner[item_pos].end_contour );
  237. if( ret < 3 )
  238. return false;
  239. }
  240. // Save the PolysList
  241. if( m_FilledPolysList.size() )
  242. {
  243. fprintf( aFile, "$POLYSCORNERS\n" );
  244. for( unsigned ii = 0; ii < m_FilledPolysList.size(); ii++ )
  245. {
  246. const CPolyPt* corner = &m_FilledPolysList[ii];
  247. ret = fprintf( aFile,
  248. "%d %d %d %d\n",
  249. corner->x,
  250. corner->y,
  251. corner->end_contour,
  252. corner->utility );
  253. if( ret < 4 )
  254. return false;
  255. }
  256. fprintf( aFile, "$endPOLYSCORNERS\n" );
  257. }
  258. // Save the filling segments list
  259. if( m_FillSegmList.size() )
  260. {
  261. fprintf( aFile, "$FILLSEGMENTS\n" );
  262. for( unsigned ii = 0; ii < m_FillSegmList.size(); ii++ )
  263. {
  264. ret = fprintf( aFile, "%d %d %d %d\n",
  265. m_FillSegmList[ii].m_Start.x, m_FillSegmList[ii].m_Start.y,
  266. m_FillSegmList[ii].m_End.x, m_FillSegmList[ii].m_End.y );
  267. if( ret < 4 )
  268. return false;
  269. }
  270. fprintf( aFile, "$endFILLSEGMENTS\n" );
  271. }
  272. fprintf( aFile, "$endCZONE_OUTLINE\n" );
  273. return true;
  274. }
  275. bool NETCLASSES::Save( FILE* aFile ) const
  276. {
  277. bool result;
  278. // save the default first.
  279. result = m_Default.Save( aFile );
  280. if( result )
  281. {
  282. // the rest will be alphabetical in the *.brd file.
  283. for( const_iterator i = begin(); i!=end(); ++i )
  284. {
  285. NETCLASS* netclass = i->second;
  286. result = netclass->Save( aFile );
  287. if( !result )
  288. break;
  289. }
  290. }
  291. return result;
  292. }
  293. bool NETCLASS::Save( FILE* aFile ) const
  294. {
  295. bool result = true;
  296. fprintf( aFile, "$NCLASS\n" );
  297. fprintf( aFile, "Name %s\n", EscapedUTF8( m_Name ).c_str() );
  298. fprintf( aFile, "Desc %s\n", EscapedUTF8( GetDescription() ).c_str() );
  299. // Write parameters
  300. fprintf( aFile, "Clearance %d\n", GetClearance() );
  301. fprintf( aFile, "TrackWidth %d\n", GetTrackWidth() );
  302. fprintf( aFile, "ViaDia %d\n", GetViaDiameter() );
  303. fprintf( aFile, "ViaDrill %d\n", GetViaDrill() );
  304. fprintf( aFile, "uViaDia %d\n", GetuViaDiameter() );
  305. fprintf( aFile, "uViaDrill %d\n", GetuViaDrill() );
  306. // Write members:
  307. for( const_iterator i = begin(); i!=end(); ++i )
  308. fprintf( aFile, "AddNet %s\n", EscapedUTF8( *i ).c_str() );
  309. fprintf( aFile, "$EndNCLASS\n" );
  310. return result;
  311. }
  312. bool TEXTE_PCB::Save( FILE* aFile ) const
  313. {
  314. if( m_Text.IsEmpty() )
  315. return true;
  316. if( fprintf( aFile, "$TEXTPCB\n" ) != sizeof("$TEXTPCB\n") - 1 )
  317. return false;
  318. const char* style = m_Italic ? "Italic" : "Normal";
  319. wxArrayString* list = wxStringSplit( m_Text, '\n' );
  320. for( unsigned ii = 0; ii < list->Count(); ii++ )
  321. {
  322. wxString txt = list->Item( ii );
  323. if ( ii == 0 )
  324. fprintf( aFile, "Te %s\n", EscapedUTF8( txt ).c_str() );
  325. else
  326. fprintf( aFile, "nl %s\n", EscapedUTF8( txt ).c_str() );
  327. }
  328. delete list;
  329. fprintf( aFile, "Po %d %d %d %d %d %g\n",
  330. m_Pos.x, m_Pos.y, m_Size.x, m_Size.y, m_Thickness, GetOrientation() );
  331. char hJustify = 'L';
  332. switch( m_HJustify )
  333. {
  334. case GR_TEXT_HJUSTIFY_LEFT:
  335. hJustify = 'L';
  336. break;
  337. case GR_TEXT_HJUSTIFY_CENTER:
  338. hJustify = 'C';
  339. break;
  340. case GR_TEXT_HJUSTIFY_RIGHT:
  341. hJustify = 'R';
  342. break;
  343. default:
  344. hJustify = 'C';
  345. break;
  346. }
  347. fprintf( aFile, "De %d %d %lX %s %c\n", m_Layer,
  348. m_Mirror ? 0 : 1,
  349. m_TimeStamp, style, hJustify );
  350. if( fprintf( aFile, "$EndTEXTPCB\n" ) != sizeof("$EndTEXTPCB\n") - 1 )
  351. return false;
  352. return true;
  353. }
  354. /**
  355. * Function Save
  356. * writes the data structures for this object out to a FILE in "*.brd" format.
  357. * @param aFile The FILE to write to.
  358. * @return bool - true if success writing else false.
  359. */
  360. bool TEXTE_MODULE::Save( FILE* aFile ) const
  361. {
  362. MODULE* parent = (MODULE*) GetParent();
  363. int orient = m_Orient;
  364. // Due to the Pcbnew history, m_Orient is saved in screen value
  365. // but it is handled as relative to its parent footprint
  366. if( parent )
  367. orient += parent->m_Orient;
  368. int ret = fprintf( aFile, "T%d %d %d %d %d %d %d %c %c %d %c %s\n",
  369. m_Type,
  370. m_Pos0.x, m_Pos0.y,
  371. m_Size.y, m_Size.x,
  372. orient,
  373. m_Thickness,
  374. m_Mirror ? 'M' : 'N', m_NoShow ? 'I' : 'V',
  375. GetLayer(),
  376. m_Italic ? 'I' : 'N',
  377. EscapedUTF8( m_Text ).c_str()
  378. );
  379. return ret > 20;
  380. }
  381. bool EDGE_MODULE::Save( FILE* aFile ) const
  382. {
  383. int ret = -1;
  384. switch( m_Shape )
  385. {
  386. case S_SEGMENT:
  387. ret = fprintf( aFile, "DS %d %d %d %d %d %d\n",
  388. m_Start0.x, m_Start0.y,
  389. m_End0.x, m_End0.y,
  390. m_Width, m_Layer );
  391. break;
  392. case S_CIRCLE:
  393. ret = fprintf( aFile, "DC %d %d %d %d %d %d\n",
  394. m_Start0.x, m_Start0.y,
  395. m_End0.x, m_End0.y,
  396. m_Width, m_Layer );
  397. break;
  398. case S_ARC:
  399. ret = fprintf( aFile, "DA %d %d %d %d %g %d %d\n",
  400. m_Start0.x, m_Start0.y,
  401. m_End0.x, m_End0.y,
  402. GetAngle(),
  403. m_Width, m_Layer );
  404. break;
  405. case S_POLYGON:
  406. ret = fprintf( aFile, "DP %d %d %d %d %d %d %d\n",
  407. m_Start0.x, m_Start0.y,
  408. m_End0.x, m_End0.y,
  409. (int) m_PolyPoints.size(),
  410. m_Width, m_Layer );
  411. for( unsigned i = 0; i<m_PolyPoints.size(); ++i )
  412. fprintf( aFile, "Dl %d %d\n", m_PolyPoints[i].x, m_PolyPoints[i].y );
  413. break;
  414. default:
  415. // future: throw an exception here
  416. #if defined(DEBUG)
  417. printf( "EDGE_MODULE::Save(): unexpected m_Shape: %d\n", m_Shape );
  418. #endif
  419. break;
  420. }
  421. return ret > 5;
  422. }
  423. bool TRACK::Save( FILE* aFile ) const
  424. {
  425. int type = 0;
  426. if( Type() == PCB_VIA_T )
  427. type = 1;
  428. fprintf( aFile, "Po %d %d %d %d %d %d %d\n", m_Shape,
  429. m_Start.x, m_Start.y, m_End.x, m_End.y, m_Width, m_Drill );
  430. fprintf( aFile, "De %d %d %d %lX %X\n",
  431. m_Layer, type, GetNet(),
  432. m_TimeStamp, GetStatus() );
  433. return true;
  434. }
  435. bool DIMENSION::Save( FILE* aFile ) const
  436. {
  437. bool rc = false;
  438. // note: COTATION was the previous name of DIMENSION
  439. // this old keyword is used here for compatibility
  440. const char keyWordLine[] = "$COTATION\n";
  441. const char keyWordLineEnd[] = "$endCOTATION\n";
  442. if( fputs( keyWordLine, aFile ) == EOF )
  443. goto out;
  444. fprintf( aFile, "Ge %d %d %lX\n", m_Shape, m_Layer, m_TimeStamp );
  445. fprintf( aFile, "Va %d\n", m_Value );
  446. if( !m_Text.GetText().IsEmpty() )
  447. fprintf( aFile, "Te %s\n", EscapedUTF8( m_Text.GetText() ).c_str() );
  448. else
  449. fprintf( aFile, "Te \"?\"\n" );
  450. fprintf( aFile, "Po %d %d %d %d %d %g %d\n",
  451. m_Text.m_Pos.x, m_Text.m_Pos.y,
  452. m_Text.m_Size.x, m_Text.m_Size.y,
  453. m_Text.GetThickness(), m_Text.GetOrientation(),
  454. m_Text.m_Mirror ? 0 : 1 );
  455. fprintf( aFile, "Sb %d %d %d %d %d %d\n", S_SEGMENT,
  456. m_crossBarOx, m_crossBarOy,
  457. m_crossBarFx, m_crossBarFy, m_Width );
  458. fprintf( aFile, "Sd %d %d %d %d %d %d\n", S_SEGMENT,
  459. m_featureLineDOx, m_featureLineDOy,
  460. m_featureLineDFx, m_featureLineDFy, m_Width );
  461. fprintf( aFile, "Sg %d %d %d %d %d %d\n", S_SEGMENT,
  462. m_featureLineGOx, m_featureLineGOy,
  463. m_featureLineGFx, m_featureLineGFy, m_Width );
  464. fprintf( aFile, "S1 %d %d %d %d %d %d\n", S_SEGMENT,
  465. m_arrowD1Ox, m_arrowD1Oy,
  466. m_arrowD1Fx, m_arrowD1Fy, m_Width );
  467. fprintf( aFile, "S2 %d %d %d %d %d %d\n", S_SEGMENT,
  468. m_arrowD2Ox, m_arrowD2Oy,
  469. m_arrowD2Fx, m_arrowD2Fy, m_Width );
  470. fprintf( aFile, "S3 %d %d %d %d %d %d\n", S_SEGMENT,
  471. m_arrowG1Ox, m_arrowG1Oy,
  472. m_arrowG1Fx, m_arrowG1Fy, m_Width );
  473. fprintf( aFile, "S4 %d %d %d %d %d %d\n", S_SEGMENT,
  474. m_arrowG2Ox, m_arrowG2Oy,
  475. m_arrowG2Fx, m_arrowG2Fy, m_Width );
  476. if( fputs( keyWordLineEnd, aFile ) == EOF )
  477. goto out;
  478. rc = true;
  479. out:
  480. return rc;
  481. }
  482. bool D_PAD::Save( FILE* aFile ) const
  483. {
  484. int cshape;
  485. const char* texttype;
  486. // check the return values for first and last fprints() in this function
  487. if( fprintf( aFile, "$PAD\n" ) != sizeof("$PAD\n") - 1 )
  488. return false;
  489. switch( m_PadShape )
  490. {
  491. case PAD_CIRCLE:
  492. cshape = 'C'; break;
  493. case PAD_RECT:
  494. cshape = 'R'; break;
  495. case PAD_OVAL:
  496. cshape = 'O'; break;
  497. case PAD_TRAPEZOID:
  498. cshape = 'T'; break;
  499. default:
  500. cshape = 'C';
  501. DisplayError( NULL, _( "Unknown pad shape" ) );
  502. break;
  503. }
  504. fprintf( aFile, "Sh \"%.4s\" %c %d %d %d %d %g\n",
  505. m_Padname, cshape, m_Size.x, m_Size.y,
  506. m_DeltaSize.x, m_DeltaSize.y, m_Orient );
  507. fprintf( aFile, "Dr %d %d %d", m_Drill.x, m_Offset.x, m_Offset.y );
  508. if( m_DrillShape == PAD_OVAL )
  509. {
  510. fprintf( aFile, " %c %d %d", 'O', m_Drill.x, m_Drill.y );
  511. }
  512. fprintf( aFile, "\n" );
  513. switch( GetAttribute() )
  514. {
  515. case PAD_STANDARD:
  516. texttype = "STD"; break;
  517. case PAD_SMD:
  518. texttype = "SMD"; break;
  519. case PAD_CONN:
  520. texttype = "CONN"; break;
  521. case PAD_HOLE_NOT_PLATED:
  522. texttype = "HOLE"; break;
  523. default:
  524. texttype = "STD";
  525. DisplayError( NULL, wxT( "Invalid Pad attribute" ) );
  526. break;
  527. }
  528. fprintf( aFile, "At %s N %8.8X\n", texttype, m_layerMask );
  529. fprintf( aFile, "Ne %d %s\n", GetNet(), EscapedUTF8( m_Netname ).c_str() );
  530. fprintf( aFile, "Po %d %d\n", m_Pos0.x, m_Pos0.y );
  531. if( GetDieLength() != 0 )
  532. fprintf( aFile, "Le %d\n", GetDieLength() );
  533. if( GetLocalSolderMaskMargin() != 0 )
  534. fprintf( aFile, ".SolderMask %d\n", GetLocalSolderMaskMargin() );
  535. if( GetLocalSolderPasteMargin() != 0 )
  536. fprintf( aFile, ".SolderPaste %d\n", GetLocalSolderPasteMargin() );
  537. if( GetLocalSolderPasteMarginRatio() != 0 )
  538. fprintf( aFile, ".SolderPasteRatio %g\n", GetLocalSolderPasteMarginRatio() );
  539. if( GetLocalClearance() != 0 )
  540. fprintf( aFile, ".LocalClearance %d\n", GetLocalClearance() );
  541. if( m_ZoneConnection != UNDEFINED_CONNECTION )
  542. fprintf( aFile, ".ZoneConnection %d\n", m_ZoneConnection );
  543. if( m_ThermalWidth != 0 )
  544. fprintf( aFile, ".ThermalWidth %d\n", m_ThermalWidth );
  545. if( m_ThermalGap != 0 )
  546. fprintf( aFile, ".ThermalGap %d\n", m_ThermalGap );
  547. if( fprintf( aFile, "$EndPAD\n" ) != sizeof("$EndPAD\n") - 1 )
  548. return false;
  549. return true;
  550. }
  551. bool MODULE::Save( FILE* aFile ) const
  552. {
  553. char statusTxt[8];
  554. BOARD_ITEM* item;
  555. bool rc = false;
  556. fprintf( aFile, "$MODULE %s\n", TO_UTF8( m_LibRef ) );
  557. memset( statusTxt, 0, sizeof(statusTxt) );
  558. if( IsLocked() )
  559. statusTxt[0] = 'F';
  560. else
  561. statusTxt[0] = '~';
  562. if( m_ModuleStatus & MODULE_is_PLACED )
  563. statusTxt[1] = 'P';
  564. else
  565. statusTxt[1] = '~';
  566. fprintf( aFile, "Po %d %d %g %d %8.8lX %8.8lX %s\n",
  567. m_Pos.x, m_Pos.y,
  568. GetOrientation(), m_Layer, m_LastEdit_Time,
  569. m_TimeStamp, statusTxt );
  570. fprintf( aFile, "Li %s\n", TO_UTF8( m_LibRef ) );
  571. if( !m_Doc.IsEmpty() )
  572. {
  573. fprintf( aFile, "Cd %s\n", TO_UTF8( m_Doc ) );
  574. }
  575. if( !m_KeyWord.IsEmpty() )
  576. {
  577. fprintf( aFile, "Kw %s\n", TO_UTF8( m_KeyWord ) );
  578. }
  579. fprintf( aFile, "Sc %8.8lX\n", m_TimeStamp );
  580. fprintf( aFile, "AR %s\n", TO_UTF8( m_Path ) );
  581. fprintf( aFile, "Op %X %X 0\n", m_CntRot90, m_CntRot180 );
  582. if( GetLocalSolderMaskMargin() != 0 )
  583. fprintf( aFile, ".SolderMask %d\n", GetLocalSolderMaskMargin() );
  584. if( m_LocalSolderPasteMargin != 0 )
  585. fprintf( aFile, ".SolderPaste %d\n", GetLocalSolderPasteMargin() );
  586. if( GetLocalSolderPasteMarginRatio() != 0 )
  587. fprintf( aFile, ".SolderPasteRatio %g\n", GetLocalSolderPasteMarginRatio() );
  588. if( m_LocalClearance != 0 )
  589. fprintf( aFile, ".LocalClearance %d\n", GetLocalClearance() );
  590. if( m_ZoneConnection != UNDEFINED_CONNECTION )
  591. fprintf( aFile, ".ZoneConnection %d\n", m_ZoneConnection );
  592. if( m_ThermalWidth != 0 )
  593. fprintf( aFile, ".ThermalWidth %d\n", m_ThermalWidth );
  594. if( m_ThermalGap != 0 )
  595. fprintf( aFile, ".ThermalGap %d\n", m_ThermalGap );
  596. // attributes
  597. if( m_Attributs != MOD_DEFAULT )
  598. {
  599. fprintf( aFile, "At " );
  600. if( m_Attributs & MOD_CMS )
  601. fprintf( aFile, "SMD " );
  602. if( m_Attributs & MOD_VIRTUAL )
  603. fprintf( aFile, "VIRTUAL " );
  604. fprintf( aFile, "\n" );
  605. }
  606. // save reference
  607. if( !m_Reference->Save( aFile ) )
  608. goto out;
  609. // save value
  610. if( !m_Value->Save( aFile ) )
  611. goto out;
  612. // save drawing elements
  613. for( item = m_Drawings; item; item = item->Next() )
  614. {
  615. switch( item->Type() )
  616. {
  617. case PCB_MODULE_TEXT_T:
  618. case PCB_MODULE_EDGE_T:
  619. if( !item->Save( aFile ) )
  620. goto out;
  621. break;
  622. default:
  623. #if defined(DEBUG)
  624. printf( "MODULE::Save() ignoring type %d\n", item->Type() );
  625. #endif
  626. break;
  627. }
  628. }
  629. // save the pads
  630. for( item = m_Pads; item; item = item->Next() )
  631. if( !item->Save( aFile ) )
  632. goto out;
  633. Write_3D_Descr( aFile );
  634. fprintf( aFile, "$EndMODULE %s\n", TO_UTF8( m_LibRef ) );
  635. rc = true;
  636. out:
  637. return rc;
  638. }
  639. /* Save the description of 3D MODULE
  640. */
  641. int MODULE::Write_3D_Descr( FILE* File ) const
  642. {
  643. char buf[512];
  644. for( S3D_MASTER* t3D = m_3D_Drawings; t3D; t3D = t3D->Next() )
  645. {
  646. if( !t3D->m_Shape3DName.IsEmpty() )
  647. {
  648. fprintf( File, "$SHAPE3D\n" );
  649. fprintf( File, "Na %s\n", EscapedUTF8( t3D->m_Shape3DName ).c_str() );
  650. sprintf( buf, "Sc %lf %lf %lf\n",
  651. t3D->m_MatScale.x,
  652. t3D->m_MatScale.y,
  653. t3D->m_MatScale.z );
  654. fprintf( File, "%s", to_point( buf ) );
  655. sprintf( buf, "Of %lf %lf %lf\n",
  656. t3D->m_MatPosition.x,
  657. t3D->m_MatPosition.y,
  658. t3D->m_MatPosition.z );
  659. fprintf( File, "%s", to_point( buf ) );
  660. sprintf( buf, "Ro %lf %lf %lf\n",
  661. t3D->m_MatRotation.x,
  662. t3D->m_MatRotation.y,
  663. t3D->m_MatRotation.z );
  664. fprintf( File, "%s", to_point( buf ) );
  665. fprintf( File, "$EndSHAPE3D\n" );
  666. }
  667. }
  668. return 0;
  669. }
  670. #endif // USE_NEW_PCBNEW_SAVE
  671. #if 1 || !defined(USE_NEW_PCBNEW_LOAD)
  672. /* Read pad from file.
  673. * The 1st line of descr ($PAD) is assumed to be already read
  674. * Syntax:
  675. * $PAD
  676. * Sh "N1" C 550 550 0 0 1800
  677. * Dr 310 0 0
  678. * At STD N 00C0FFFF
  679. * Do 3 "netname"
  680. * Po 6000 -6000
  681. * $EndPAD
  682. */
  683. int D_PAD::ReadDescr( LINE_READER* aReader )
  684. {
  685. char* Line;
  686. char BufLine[1024], BufCar[256];
  687. char* PtLine;
  688. int nn, ll, dx, dy;
  689. while( aReader->ReadLine() )
  690. {
  691. Line = aReader->Line();
  692. if( Line[0] == '$' )
  693. return 0;
  694. PtLine = Line + 3;
  695. /* Decode the first code and read the corresponding data
  696. */
  697. switch( Line[0] )
  698. {
  699. case 'S': // = Sh
  700. // Read pad name
  701. nn = 0;
  702. while( (*PtLine != '"') && *PtLine )
  703. PtLine++;
  704. if( *PtLine )
  705. PtLine++;
  706. memset( m_Padname, 0, sizeof(m_Padname) );
  707. while( (*PtLine != '"') && *PtLine )
  708. {
  709. if( nn < (int) sizeof(m_Padname) )
  710. {
  711. if( *PtLine > ' ' )
  712. {
  713. m_Padname[nn] = *PtLine; nn++;
  714. }
  715. }
  716. PtLine++;
  717. }
  718. if( *PtLine == '"' )
  719. PtLine++;
  720. nn = sscanf( PtLine, " %s %d %d %d %d %lf",
  721. BufCar, &m_Size.x, &m_Size.y,
  722. &m_DeltaSize.x, &m_DeltaSize.y,
  723. &m_Orient );
  724. ll = 0xFF & BufCar[0];
  725. // Read pad shape
  726. PAD_SHAPE_T shape;
  727. switch( ll )
  728. {
  729. default:
  730. case 'C': shape = PAD_CIRCLE; break;
  731. case 'R': shape = PAD_RECT; break;
  732. case 'O': shape = PAD_OVAL; break;
  733. case 'T': shape = PAD_TRAPEZOID; break;
  734. }
  735. SetShape( shape ); // sets m_boundingRadius = -1
  736. break;
  737. case 'D':
  738. BufCar[0] = 0;
  739. nn = sscanf( PtLine, "%d %d %d %s %d %d", &m_Drill.x,
  740. &m_Offset.x, &m_Offset.y, BufCar, &dx, &dy );
  741. m_Drill.y = m_Drill.x;
  742. m_DrillShape = PAD_CIRCLE;
  743. if( nn >= 6 ) // Drill shape = OVAL ?
  744. {
  745. if( BufCar[0] == 'O' )
  746. {
  747. m_Drill.x = dx;
  748. m_Drill.y = dy;
  749. m_DrillShape = PAD_OVAL;
  750. }
  751. }
  752. break;
  753. case 'A':
  754. nn = sscanf( PtLine, "%s %s %X", BufLine, BufCar,
  755. &m_layerMask );
  756. // BufCar is not used now update attributes
  757. SetAttribute( PAD_STANDARD );
  758. if( strncmp( BufLine, "SMD", 3 ) == 0 )
  759. SetAttribute( PAD_SMD );
  760. if( strncmp( BufLine, "CONN", 4 ) == 0 )
  761. SetAttribute( PAD_CONN );
  762. if( strncmp( BufLine, "HOLE", 4 ) == 0 )
  763. SetAttribute( PAD_HOLE_NOT_PLATED );
  764. break;
  765. case 'N': // Read Netname
  766. int netcode;
  767. nn = sscanf( PtLine, "%d", &netcode );
  768. SetNet( netcode );
  769. // read Netname
  770. ReadDelimitedText( BufLine, PtLine, sizeof(BufLine) );
  771. SetNetname( FROM_UTF8( StrPurge( BufLine ) ) );
  772. break;
  773. case 'P':
  774. nn = sscanf( PtLine, "%d %d", &m_Pos0.x, &m_Pos0.y );
  775. m_Pos = m_Pos0;
  776. break;
  777. case 'L':
  778. int lengthdie;
  779. nn = sscanf( PtLine, "%d", &lengthdie );
  780. SetDieLength( lengthdie );
  781. break;
  782. case '.': // Read specific data
  783. if( strnicmp( Line, ".SolderMask ", 12 ) == 0 )
  784. SetLocalSolderMaskMargin( atoi( Line + 12 ) );
  785. else if( strnicmp( Line, ".SolderPaste ", 13 ) == 0 )
  786. SetLocalSolderPasteMargin( atoi( Line + 13 ) );
  787. else if( strnicmp( Line, ".SolderPasteRatio ", 18 ) == 0 )
  788. SetLocalSolderPasteMarginRatio( atoi( Line + 18 ) );
  789. else if( strnicmp( Line, ".LocalClearance ", 16 ) == 0 )
  790. SetLocalClearance( atoi( Line + 16 ) );
  791. else if( strnicmp( Line, ".ZoneConnection ", 16 ) == 0 )
  792. m_ZoneConnection = (ZoneConnection)atoi( Line + 16 );
  793. else if( strnicmp( Line, ".ThermalWidth ", 14 ) == 0 )
  794. m_ThermalWidth = atoi( Line + 14 );
  795. else if( strnicmp( Line, ".ThermalGap ", 12 ) == 0 )
  796. m_ThermalGap = atoi( Line + 12 );
  797. break;
  798. default:
  799. DisplayError( NULL, wxT( "Err Pad: Id inconnu" ) );
  800. return 1;
  801. }
  802. }
  803. return 2; // error : EOF
  804. }
  805. /* Read 3D module from file. (Ascii)
  806. * The 1st line of descr ($MODULE) is assumed to be already read
  807. * Returns 0 if OK
  808. */
  809. int MODULE::Read_3D_Descr( LINE_READER* aReader )
  810. {
  811. char* Line = aReader->Line();
  812. char* text = Line + 3;
  813. S3D_MASTER* t3D = m_3D_Drawings;
  814. if( !t3D->m_Shape3DName.IsEmpty() )
  815. {
  816. S3D_MASTER* n3D = new S3D_MASTER( this );
  817. m_3D_Drawings.PushBack( n3D );
  818. t3D = n3D;
  819. }
  820. while( aReader->ReadLine() )
  821. {
  822. Line = aReader->Line();
  823. switch( Line[0] )
  824. {
  825. case '$':
  826. if( Line[1] == 'E' )
  827. return 0;
  828. return 1;
  829. case 'N': // Shape File Name
  830. {
  831. char buf[512];
  832. ReadDelimitedText( buf, text, 512 );
  833. t3D->m_Shape3DName = FROM_UTF8( buf );
  834. break;
  835. }
  836. case 'S': // Scale
  837. sscanf( text, "%lf %lf %lf\n",
  838. &t3D->m_MatScale.x,
  839. &t3D->m_MatScale.y,
  840. &t3D->m_MatScale.z );
  841. break;
  842. case 'O': // Offset
  843. sscanf( text, "%lf %lf %lf\n",
  844. &t3D->m_MatPosition.x,
  845. &t3D->m_MatPosition.y,
  846. &t3D->m_MatPosition.z );
  847. break;
  848. case 'R': // Rotation
  849. sscanf( text, "%lf %lf %lf\n",
  850. &t3D->m_MatRotation.x,
  851. &t3D->m_MatRotation.y,
  852. &t3D->m_MatRotation.z );
  853. break;
  854. default:
  855. break;
  856. }
  857. }
  858. return 1;
  859. }
  860. /* Read a MODULE description
  861. * The first description line ($MODULE) is already read
  862. * @return 0 if no error
  863. */
  864. int MODULE::ReadDescr( LINE_READER* aReader )
  865. {
  866. char* Line;
  867. char BufLine[256], BufCar1[128], * PtLine;
  868. int itmp1, itmp2;
  869. while( aReader->ReadLine() )
  870. {
  871. Line = aReader->Line();
  872. if( Line[0] == '$' )
  873. {
  874. if( Line[1] == 'E' )
  875. break;
  876. if( Line[1] == 'P' )
  877. {
  878. D_PAD* pad = new D_PAD( this );
  879. pad->ReadDescr( aReader );
  880. wxPoint padpos = pad->GetPosition();
  881. RotatePoint( &padpos, m_Orient );
  882. pad->SetPosition( padpos + m_Pos );
  883. m_Pads.PushBack( pad );
  884. continue;
  885. }
  886. if( Line[1] == 'S' )
  887. Read_3D_Descr( aReader );
  888. }
  889. if( strlen( Line ) < 4 )
  890. continue;
  891. PtLine = Line + 3;
  892. /* Decode the first code of the current line and read the
  893. * corresponding data
  894. */
  895. switch( Line[0] )
  896. {
  897. case 'P':
  898. double orientation;
  899. memset( BufCar1, 0, sizeof(BufCar1) );
  900. sscanf( PtLine, "%d %d %lf %d %lX %lX %s",
  901. &m_Pos.x, &m_Pos.y,
  902. &orientation, &m_Layer,
  903. &m_LastEdit_Time, &m_TimeStamp, BufCar1 );
  904. SetOrientation( orientation );
  905. m_ModuleStatus = 0;
  906. if( BufCar1[0] == 'F' )
  907. SetLocked( true );
  908. if( BufCar1[1] == 'P' )
  909. m_ModuleStatus |= MODULE_is_PLACED;
  910. break;
  911. case 'L': // Li = read the library name of the footprint
  912. *BufLine = 0;
  913. sscanf( PtLine, " %s", BufLine );
  914. m_LibRef = FROM_UTF8( BufLine );
  915. break;
  916. case 'S':
  917. sscanf( PtLine, " %lX", &m_TimeStamp );
  918. break;
  919. case 'O': // (Op)tions for auto placement
  920. itmp1 = itmp2 = 0;
  921. sscanf( PtLine, " %X %X", &itmp1, &itmp2 );
  922. m_CntRot180 = itmp2 & 0x0F;
  923. if( m_CntRot180 > 10 )
  924. m_CntRot180 = 10;
  925. m_CntRot90 = itmp1 & 0x0F;
  926. if( m_CntRot90 > 10 )
  927. m_CntRot90 = 0;
  928. itmp1 = (itmp1 >> 4) & 0x0F;
  929. if( itmp1 > 10 )
  930. itmp1 = 0;
  931. m_CntRot90 |= itmp1 << 4;
  932. break;
  933. case 'A':
  934. if( Line[1] == 't' )
  935. {
  936. // At = (At)tributes of module
  937. if( strstr( PtLine, "SMD" ) )
  938. m_Attributs |= MOD_CMS;
  939. if( strstr( PtLine, "VIRTUAL" ) )
  940. m_Attributs |= MOD_VIRTUAL;
  941. }
  942. if( Line[1] == 'R' )
  943. {
  944. // alternate reference, e.g. /478C2408/478AD1B6
  945. sscanf( PtLine, " %s", BufLine );
  946. m_Path = FROM_UTF8( BufLine );
  947. }
  948. break;
  949. case 'T': /* Read a footprint text description (ref, value, or
  950. * drawing */
  951. TEXTE_MODULE * textm;
  952. sscanf( Line + 1, "%d", &itmp1 );
  953. if( itmp1 == TEXT_is_REFERENCE )
  954. textm = m_Reference;
  955. else if( itmp1 == TEXT_is_VALUE )
  956. textm = m_Value;
  957. else // text is a drawing
  958. {
  959. textm = new TEXTE_MODULE( this );
  960. m_Drawings.PushBack( textm );
  961. }
  962. textm->ReadDescr( aReader );
  963. break;
  964. case 'D': // read a drawing item
  965. EDGE_MODULE * edge;
  966. edge = new EDGE_MODULE( this );
  967. m_Drawings.PushBack( edge );
  968. edge->ReadDescr( aReader );
  969. edge->SetDrawCoord();
  970. break;
  971. case 'C': // read documentation data
  972. m_Doc = FROM_UTF8( StrPurge( PtLine ) );
  973. break;
  974. case 'K': // Read key words
  975. m_KeyWord = FROM_UTF8( StrPurge( PtLine ) );
  976. break;
  977. case '.': // Read specific data
  978. if( strnicmp( Line, ".SolderMask ", 12 ) == 0 )
  979. SetLocalSolderMaskMargin( atoi( Line + 12 ) );
  980. else if( strnicmp( Line, ".SolderPaste ", 13 ) == 0 )
  981. SetLocalSolderPasteMargin( atoi( Line + 13 ) );
  982. else if( strnicmp( Line, ".SolderPasteRatio ", 18 ) == 0 )
  983. SetLocalSolderPasteMarginRatio( atof( Line + 18 ) );
  984. else if( strnicmp( Line, ".LocalClearance ", 16 ) == 0 )
  985. SetLocalClearance( atoi( Line + 16 ) );
  986. else if( strnicmp( Line, ".ZoneConnection ", 16 ) == 0 )
  987. m_ZoneConnection = (ZoneConnection)atoi( Line + 16 );
  988. else if( strnicmp( Line, ".ThermalWidth ", 14 ) == 0 )
  989. m_ThermalWidth = atoi( Line + 14 );
  990. else if( strnicmp( Line, ".ThermalGap ", 12 ) == 0 )
  991. m_ThermalGap = atoi( Line + 12 );
  992. break;
  993. default:
  994. break;
  995. }
  996. }
  997. // Recalculate the bounding box
  998. CalculateBoundingBox();
  999. return 0;
  1000. }
  1001. /* Read a description line like:
  1002. * DS 2600 0 2600 -600 120 21
  1003. * this description line is in Line
  1004. * EDGE_MODULE type can be:
  1005. * - Circle,
  1006. * - Segment (line)
  1007. * - Arc
  1008. * - Polygon
  1009. *
  1010. */
  1011. int EDGE_MODULE::ReadDescr( LINE_READER* aReader )
  1012. {
  1013. int ii;
  1014. int error = 0;
  1015. char* Buf;
  1016. char* Line;
  1017. Line = aReader->Line();
  1018. switch( Line[1] )
  1019. {
  1020. case 'S':
  1021. m_Shape = S_SEGMENT;
  1022. break;
  1023. case 'C':
  1024. m_Shape = S_CIRCLE;
  1025. break;
  1026. case 'A':
  1027. m_Shape = S_ARC;
  1028. break;
  1029. case 'P':
  1030. m_Shape = S_POLYGON;
  1031. break;
  1032. default:
  1033. wxString msg;
  1034. msg.Printf( wxT( "Unknown EDGE_MODULE type <%s>" ), Line );
  1035. DisplayError( NULL, msg );
  1036. error = 1;
  1037. break;
  1038. }
  1039. switch( m_Shape )
  1040. {
  1041. case S_ARC:
  1042. double angle;
  1043. sscanf( Line + 3, "%d %d %d %d %lf %d %d",
  1044. &m_Start0.x, &m_Start0.y,
  1045. &m_End0.x, &m_End0.y,
  1046. &angle, &m_Width, &m_Layer );
  1047. NORMALIZE_ANGLE_360( angle );
  1048. SetAngle( angle );
  1049. break;
  1050. case S_SEGMENT:
  1051. case S_CIRCLE:
  1052. sscanf( Line + 3, "%d %d %d %d %d %d",
  1053. &m_Start0.x, &m_Start0.y,
  1054. &m_End0.x, &m_End0.y,
  1055. &m_Width, &m_Layer );
  1056. break;
  1057. case S_POLYGON:
  1058. int pointCount;
  1059. sscanf( Line + 3, "%d %d %d %d %d %d %d",
  1060. &m_Start0.x, &m_Start0.y,
  1061. &m_End0.x, &m_End0.y,
  1062. &pointCount, &m_Width, &m_Layer );
  1063. m_PolyPoints.clear();
  1064. m_PolyPoints.reserve( pointCount );
  1065. for( ii = 0; ii<pointCount; ii++ )
  1066. {
  1067. if( aReader->ReadLine() )
  1068. {
  1069. Buf = aReader->Line();
  1070. if( strncmp( Buf, "Dl", 2 ) != 0 )
  1071. {
  1072. error = 1;
  1073. break;
  1074. }
  1075. int x;
  1076. int y;
  1077. sscanf( Buf + 3, "%d %d\n", &x, &y );
  1078. m_PolyPoints.push_back( wxPoint( x, y ) );
  1079. }
  1080. else
  1081. {
  1082. error = 1;
  1083. break;
  1084. }
  1085. }
  1086. break;
  1087. default:
  1088. sscanf( Line + 3, "%d %d %d %d %d %d",
  1089. &m_Start0.x, &m_Start0.y,
  1090. &m_End0.x, &m_End0.y,
  1091. &m_Width, &m_Layer );
  1092. break;
  1093. }
  1094. // Check for a reasonable width:
  1095. if( m_Width <= 1 )
  1096. m_Width = 1;
  1097. if( m_Width > MAX_WIDTH )
  1098. m_Width = MAX_WIDTH;
  1099. // Check for a reasonable layer:
  1100. // m_Layer must be >= FIRST_NON_COPPER_LAYER, but because microwave footprints
  1101. // can use the copper layers m_Layer < FIRST_NON_COPPER_LAYER is allowed.
  1102. // @todo: changes use of EDGE_MODULE these footprints and allows only
  1103. // m_Layer >= FIRST_NON_COPPER_LAYER
  1104. if( (m_Layer < 0) || (m_Layer > LAST_NON_COPPER_LAYER) )
  1105. m_Layer = SILKSCREEN_N_FRONT;
  1106. return error;
  1107. }
  1108. bool DIMENSION::ReadDimensionDescr( LINE_READER* aReader )
  1109. {
  1110. char* Line;
  1111. char Text[2048];
  1112. while( aReader->ReadLine() )
  1113. {
  1114. Line = aReader->Line();
  1115. if( strnicmp( Line, "$EndDIMENSION", 4 ) == 0 )
  1116. return true;
  1117. if( Line[0] == 'V' )
  1118. {
  1119. sscanf( Line + 2, " %d", &m_Value );
  1120. continue;
  1121. }
  1122. if( Line[0] == 'G' )
  1123. {
  1124. int layer;
  1125. sscanf( Line + 2, " %d %d %lX", &m_Shape, &layer, &m_TimeStamp );
  1126. if( layer < FIRST_NO_COPPER_LAYER )
  1127. layer = FIRST_NO_COPPER_LAYER;
  1128. if( layer > LAST_NO_COPPER_LAYER )
  1129. layer = LAST_NO_COPPER_LAYER;
  1130. SetLayer( layer );
  1131. m_Text.SetLayer( layer );
  1132. continue;
  1133. }
  1134. if( Line[0] == 'T' )
  1135. {
  1136. ReadDelimitedText( Text, Line + 2, sizeof(Text) );
  1137. m_Text.m_Text = FROM_UTF8( Text );
  1138. continue;
  1139. }
  1140. if( Line[0] == 'P' )
  1141. {
  1142. int normal_display = 1;
  1143. int orientation;
  1144. int thickness;
  1145. sscanf( Line + 2, " %d %d %d %d %d %d %d",
  1146. &m_Text.m_Pos.x, &m_Text.m_Pos.y,
  1147. &m_Text.m_Size.x, &m_Text.m_Size.y,
  1148. &thickness, &orientation,
  1149. &normal_display );
  1150. m_Text.m_Mirror = normal_display ? false : true;
  1151. m_Pos = m_Text.m_Pos;
  1152. m_Text.SetOrientation( orientation );
  1153. m_Text.SetThickness( thickness );
  1154. continue;
  1155. }
  1156. if( Line[0] == 'S' )
  1157. {
  1158. switch( Line[1] )
  1159. {
  1160. int Dummy;
  1161. case 'b':
  1162. sscanf( Line + 2, " %d %d %d %d %d %d",
  1163. &Dummy,
  1164. &m_crossBarOx, &m_crossBarOy,
  1165. &m_crossBarFx, &m_crossBarFy,
  1166. &m_Width );
  1167. break;
  1168. case 'd':
  1169. sscanf( Line + 2, " %d %d %d %d %d %d",
  1170. &Dummy,
  1171. &m_featureLineDOx, &m_featureLineDOy,
  1172. &m_featureLineDFx, &m_featureLineDFy,
  1173. &Dummy );
  1174. break;
  1175. case 'g':
  1176. sscanf( Line + 2, " %d %d %d %d %d %d",
  1177. &Dummy,
  1178. &m_featureLineGOx, &m_featureLineGOy,
  1179. &m_featureLineGFx, &m_featureLineGFy,
  1180. &Dummy );
  1181. break;
  1182. case '1':
  1183. sscanf( Line + 2, " %d %d %d %d %d %d",
  1184. &Dummy,
  1185. &m_arrowD1Ox, &m_arrowD1Oy,
  1186. &m_arrowD1Fx, &m_arrowD1Fy,
  1187. &Dummy );
  1188. break;
  1189. case '2':
  1190. sscanf( Line + 2, " %d %d %d %d %d %d",
  1191. &Dummy,
  1192. &m_arrowD2Ox, &m_arrowD2Oy,
  1193. &m_arrowD2Fx, &m_arrowD2Fy,
  1194. &Dummy );
  1195. break;
  1196. case '3':
  1197. sscanf( Line + 2, " %d %d %d %d %d %d\n",
  1198. &Dummy,
  1199. &m_arrowG1Ox, &m_arrowG1Oy,
  1200. &m_arrowG1Fx, &m_arrowG1Fy,
  1201. &Dummy );
  1202. break;
  1203. case '4':
  1204. sscanf( Line + 2, " %d %d %d %d %d %d",
  1205. &Dummy,
  1206. &m_arrowG2Ox, &m_arrowG2Oy,
  1207. &m_arrowG2Fx, &m_arrowG2Fy,
  1208. &Dummy );
  1209. break;
  1210. }
  1211. continue;
  1212. }
  1213. }
  1214. return false;
  1215. }
  1216. bool DRAWSEGMENT::ReadDrawSegmentDescr( LINE_READER* aReader )
  1217. {
  1218. char* Line;
  1219. while( aReader->ReadLine() )
  1220. {
  1221. Line = aReader->Line();
  1222. if( strnicmp( Line, "$End", 4 ) == 0 )
  1223. return true; // End of description
  1224. if( Line[0] == 'P' )
  1225. {
  1226. sscanf( Line + 2, " %d %d %d %d %d %d",
  1227. &m_Shape, &m_Start.x, &m_Start.y,
  1228. &m_End.x, &m_End.y, &m_Width );
  1229. if( m_Width < 0 )
  1230. m_Width = 0;
  1231. }
  1232. if( Line[0] == 'D' )
  1233. {
  1234. int status;
  1235. char* token = 0;
  1236. token = strtok( Line," " );
  1237. for( int i = 0; (token = strtok( NULL," " )) != NULL; i++ )
  1238. {
  1239. switch( i )
  1240. {
  1241. case 0:
  1242. sscanf( token,"%d",&m_Layer );
  1243. break;
  1244. case 1:
  1245. sscanf( token,"%d",&m_Type );
  1246. break;
  1247. case 2:
  1248. double angle;
  1249. sscanf( token, "%lf", &angle );
  1250. SetAngle( angle );
  1251. break;
  1252. case 3:
  1253. sscanf( token,"%lX",&m_TimeStamp );
  1254. break;
  1255. case 4:
  1256. sscanf( token,"%X",&status );
  1257. break;
  1258. // Bezier Control Points
  1259. case 5:
  1260. sscanf( token,"%d",&m_BezierC1.x );
  1261. break;
  1262. case 6:
  1263. sscanf( token,"%d",&m_BezierC1.y );
  1264. break;
  1265. case 7:
  1266. sscanf( token,"%d",&m_BezierC2.x );
  1267. break;
  1268. case 8:
  1269. sscanf( token,"%d",&m_BezierC2.y );
  1270. break;
  1271. default:
  1272. break;
  1273. }
  1274. }
  1275. if( m_Layer < FIRST_NO_COPPER_LAYER )
  1276. m_Layer = FIRST_NO_COPPER_LAYER;
  1277. if( m_Layer > LAST_NO_COPPER_LAYER )
  1278. m_Layer = LAST_NO_COPPER_LAYER;
  1279. SetState( status, ON );
  1280. }
  1281. }
  1282. return false;
  1283. }
  1284. /* Read NETINFO_ITEM from file.
  1285. * Returns 0 if OK
  1286. * 1 if incomplete reading
  1287. */
  1288. int NETINFO_ITEM::ReadDescr( LINE_READER* aReader )
  1289. {
  1290. char* Line;
  1291. char Ltmp[1024];
  1292. int tmp;
  1293. while( aReader->ReadLine() )
  1294. {
  1295. Line = aReader->Line();
  1296. if( strnicmp( Line, "$End", 4 ) == 0 )
  1297. return 0;
  1298. if( strncmp( Line, "Na", 2 ) == 0 )
  1299. {
  1300. sscanf( Line + 2, " %d", &tmp );
  1301. SetNet( tmp );
  1302. ReadDelimitedText( Ltmp, Line + 2, sizeof(Ltmp) );
  1303. m_Netname = FROM_UTF8( Ltmp );
  1304. continue;
  1305. }
  1306. }
  1307. return 1;
  1308. }
  1309. /* Read the description from the PCB file.
  1310. */
  1311. bool PCB_TARGET::ReadMirePcbDescr( LINE_READER* aReader )
  1312. {
  1313. char* Line;
  1314. while( aReader->ReadLine() )
  1315. {
  1316. Line = aReader->Line();
  1317. if( strnicmp( Line, "$End", 4 ) == 0 )
  1318. return true;
  1319. if( Line[0] == 'P' )
  1320. {
  1321. sscanf( Line + 2, " %X %d %d %d %d %d %lX",
  1322. &m_Shape, &m_Layer,
  1323. &m_Pos.x, &m_Pos.y,
  1324. &m_Size, &m_Width, &m_TimeStamp );
  1325. if( m_Layer < FIRST_NO_COPPER_LAYER )
  1326. m_Layer = FIRST_NO_COPPER_LAYER;
  1327. if( m_Layer > LAST_NO_COPPER_LAYER )
  1328. m_Layer = LAST_NO_COPPER_LAYER;
  1329. }
  1330. }
  1331. return false;
  1332. }
  1333. int ZONE_CONTAINER::ReadDescr( LINE_READER* aReader )
  1334. {
  1335. char* Line, * text;
  1336. char netname_buffer[1024];
  1337. int ret;
  1338. int outline_hatch = CPolyLine::NO_HATCH;
  1339. bool error = false, has_corner = false;
  1340. netname_buffer[0] = 0;
  1341. while( aReader->ReadLine() )
  1342. {
  1343. Line = aReader->Line();
  1344. if( strnicmp( Line, "ZCorner", 7 ) == 0 ) // new corner found
  1345. {
  1346. int x;
  1347. int y;
  1348. int flag;
  1349. text = Line + 7;
  1350. ret = sscanf( text, "%d %d %d", &x, &y, &flag );
  1351. if( ret < 3 )
  1352. {
  1353. error = true;
  1354. }
  1355. else
  1356. {
  1357. if( !has_corner )
  1358. m_Poly->Start( m_Layer, x, y, outline_hatch );
  1359. else
  1360. AppendCorner( wxPoint( x, y ) );
  1361. has_corner = true;
  1362. if( flag )
  1363. m_Poly->Close();
  1364. }
  1365. }
  1366. else if( strnicmp( Line, "ZInfo", 5 ) == 0 ) // general info found
  1367. {
  1368. int ts;
  1369. int netcode;
  1370. text = Line + 5;
  1371. ret = sscanf( text, "%X %d %s", &ts, &netcode, netname_buffer );
  1372. if( ret < 3 )
  1373. {
  1374. error = true;
  1375. }
  1376. else
  1377. {
  1378. SetTimeStamp( ts );
  1379. SetNet( netcode );
  1380. ReadDelimitedText( netname_buffer, netname_buffer, 1024 );
  1381. m_Netname = FROM_UTF8( netname_buffer );
  1382. }
  1383. }
  1384. else if( strnicmp( Line, "ZLayer", 6 ) == 0 ) // layer found
  1385. {
  1386. int x;
  1387. text = Line + 6;
  1388. ret = sscanf( text, "%d", &x );
  1389. if( ret < 1 )
  1390. error = true;
  1391. else
  1392. m_Layer = x;
  1393. }
  1394. else if( strnicmp( Line, "ZAux", 4 ) == 0 ) // aux info found
  1395. {
  1396. int x;
  1397. char hopt[10];
  1398. text = Line + 4;
  1399. ret = sscanf( text, "%d %c", &x, hopt );
  1400. if( ret < 2 )
  1401. {
  1402. error = true;
  1403. }
  1404. else
  1405. {
  1406. switch( hopt[0] )
  1407. {
  1408. case 'n':
  1409. case 'N':
  1410. outline_hatch = CPolyLine::NO_HATCH;
  1411. break;
  1412. case 'e':
  1413. case 'E':
  1414. outline_hatch = CPolyLine::DIAGONAL_EDGE;
  1415. break;
  1416. case 'f':
  1417. case 'F':
  1418. outline_hatch = CPolyLine::DIAGONAL_FULL;
  1419. break;
  1420. }
  1421. }
  1422. // Set hatch mode later, after reading outlines corners data
  1423. }
  1424. else if( strnicmp( Line, "ZPriority", 9 ) == 0 )
  1425. {
  1426. int tmp = 0;
  1427. text = Line + 9;
  1428. ret = sscanf( text, "%d", &tmp );
  1429. if( ret < 1 )
  1430. return false;
  1431. SetPriority( tmp );
  1432. }
  1433. else if( strnicmp( Line, "ZSmoothing", 10 ) == 0 )
  1434. {
  1435. int tempSmoothingType;
  1436. int tempCornerRadius;
  1437. text = Line + 10;
  1438. ret = sscanf( text, "%d %d", &tempSmoothingType, &tempCornerRadius );
  1439. if( ret < 2 )
  1440. return false;
  1441. if( tempSmoothingType >= ZONE_SETTINGS::SMOOTHING_LAST )
  1442. return false;
  1443. if( tempSmoothingType < 0 )
  1444. return false;
  1445. cornerSmoothingType = tempSmoothingType;
  1446. SetCornerRadius( tempCornerRadius );
  1447. }
  1448. else if( strnicmp( Line, "ZOptions", 8 ) == 0 ) // Options info found
  1449. {
  1450. int fillmode = 1;
  1451. int arcsegmentcount = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF;
  1452. char fillstate = 'F';
  1453. text = Line + 8;
  1454. ret = sscanf( text, "%d %d %c %d %d", &fillmode, &arcsegmentcount, &fillstate,
  1455. &m_ThermalReliefGap, &m_ThermalReliefCopperBridge );
  1456. if( ret < 1 ) // Must find 1 or more args.
  1457. return false;
  1458. else
  1459. m_FillMode = fillmode ? 1 : 0;
  1460. if( arcsegmentcount >= ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF )
  1461. m_ArcToSegmentsCount = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF;
  1462. m_IsFilled = (fillstate == 'S') ? true : false;
  1463. }
  1464. else if( strnicmp( Line, "ZClearance", 10 ) == 0 ) // Clearance and pad options info found
  1465. {
  1466. int clearance = 200;
  1467. char padConnection;
  1468. text = Line + 10;
  1469. ret = sscanf( text, "%d %1c", &clearance, &padConnection );
  1470. if( ret < 2 )
  1471. {
  1472. error = true;
  1473. }
  1474. else
  1475. {
  1476. m_ZoneClearance = clearance;
  1477. switch( padConnection )
  1478. {
  1479. case 'i':
  1480. case 'I':
  1481. m_PadConnection = PAD_IN_ZONE;
  1482. break;
  1483. case 't':
  1484. case 'T':
  1485. m_PadConnection = THERMAL_PAD;
  1486. break;
  1487. case 'x':
  1488. case 'X':
  1489. m_PadConnection = PAD_NOT_IN_ZONE;
  1490. break;
  1491. }
  1492. }
  1493. }
  1494. else if( strnicmp( Line, "ZMinThickness", 13 ) == 0 ) // Min Thickness info found
  1495. {
  1496. int thickness;
  1497. text = Line + 13;
  1498. ret = sscanf( text, "%d", &thickness );
  1499. if( ret < 1 )
  1500. error = true;
  1501. else
  1502. m_ZoneMinThickness = thickness;
  1503. }
  1504. else if( strnicmp( Line, "$POLYSCORNERS", 13 ) == 0 ) // Read the PolysList (polygons used for fill areas in the zone)
  1505. {
  1506. while( aReader->ReadLine() )
  1507. {
  1508. Line = aReader->Line();
  1509. if( strnicmp( Line, "$endPOLYSCORNERS", 4 ) == 0 )
  1510. break;
  1511. CPolyPt corner;
  1512. int end_contour, utility;
  1513. utility = 0;
  1514. ret = sscanf( Line,
  1515. "%d %d %d %d",
  1516. &corner.x,
  1517. &corner.y,
  1518. &end_contour,
  1519. &utility );
  1520. if( ret < 4 )
  1521. return false;
  1522. corner.end_contour = end_contour ? true : false;
  1523. corner.utility = utility;
  1524. m_FilledPolysList.push_back( corner );
  1525. }
  1526. }
  1527. else if( strnicmp( Line, "$FILLSEGMENTS", 13 ) == 0 )
  1528. {
  1529. SEGMENT segm;
  1530. while( aReader->ReadLine() )
  1531. {
  1532. Line = aReader->Line();
  1533. if( strnicmp( Line, "$endFILLSEGMENTS", 4 ) == 0 )
  1534. break;
  1535. ret = sscanf( Line,
  1536. "%d %d %d %d",
  1537. &segm.m_Start.x,
  1538. &segm.m_Start.y,
  1539. &segm.m_End.x,
  1540. &segm.m_End.y );
  1541. if( ret < 4 )
  1542. return false;
  1543. m_FillSegmList.push_back( segm );
  1544. }
  1545. }
  1546. else if( strnicmp( Line, "$end", 4 ) == 0 ) // end of description
  1547. {
  1548. break;
  1549. }
  1550. }
  1551. if( !IsOnCopperLayer() )
  1552. {
  1553. m_FillMode = 0;
  1554. SetNet( 0 );
  1555. }
  1556. // Set hatch here, when outlines corners are read
  1557. m_Poly->SetHatch( outline_hatch, Mils2iu( m_Poly->GetDefaultHatchPitchMils() ) );
  1558. return error ? 0 : 1;
  1559. }
  1560. bool NETCLASS::ReadDescr( LINE_READER* aReader )
  1561. {
  1562. bool result = false;
  1563. char* line;
  1564. char buf[1024];
  1565. wxString netname;
  1566. while( aReader->ReadLine() )
  1567. {
  1568. line = aReader->Line();
  1569. if( strnicmp( line, "AddNet", 6 ) == 0 )
  1570. {
  1571. ReadDelimitedText( buf, line + 6, sizeof(buf) );
  1572. netname = FROM_UTF8( buf );
  1573. Add( netname );
  1574. continue;
  1575. }
  1576. if( strnicmp( line, "$endNCLASS", sizeof( "$endNCLASS" ) - 1 ) == 0 )
  1577. {
  1578. result = true;
  1579. break;
  1580. }
  1581. if( strnicmp( line, "Clearance", 9 ) == 0 )
  1582. {
  1583. SetClearance( atoi( line + 9 ) );
  1584. continue;
  1585. }
  1586. if( strnicmp( line, "TrackWidth", 10 ) == 0 )
  1587. {
  1588. SetTrackWidth( atoi( line + 10 ) );
  1589. continue;
  1590. }
  1591. if( strnicmp( line, "ViaDia", 6 ) == 0 )
  1592. {
  1593. SetViaDiameter( atoi( line + 6 ) );
  1594. continue;
  1595. }
  1596. if( strnicmp( line, "ViaDrill", 8 ) == 0 )
  1597. {
  1598. SetViaDrill( atoi( line + 8 ) );
  1599. continue;
  1600. }
  1601. if( strnicmp( line, "uViaDia", 7 ) == 0 )
  1602. {
  1603. SetuViaDiameter( atoi( line + 7 ) );
  1604. continue;
  1605. }
  1606. if( strnicmp( line, "uViaDrill", 9 ) == 0 )
  1607. {
  1608. SetuViaDrill( atoi( line + 9 ) );
  1609. continue;
  1610. }
  1611. if( strnicmp( line, "Name", 4 ) == 0 )
  1612. {
  1613. ReadDelimitedText( buf, line + 4, sizeof(buf) );
  1614. m_Name = FROM_UTF8( buf );
  1615. continue;
  1616. }
  1617. if( strnicmp( line, "Desc", 4 ) == 0 )
  1618. {
  1619. ReadDelimitedText( buf, line + 4, sizeof(buf) );
  1620. SetDescription( FROM_UTF8( buf ) );
  1621. continue;
  1622. }
  1623. }
  1624. return result;
  1625. }
  1626. /**
  1627. * Function ReadTextePcbDescr
  1628. * Read a text description from pcb file.
  1629. *
  1630. * For a single line text:
  1631. *
  1632. * $TEXTPCB
  1633. * Te "Text example"
  1634. * Po 66750 53450 600 800 150 0
  1635. * From 24 1 0 Italic
  1636. * $EndTEXTPCB
  1637. *
  1638. * For a multi line text
  1639. *
  1640. * $TEXTPCB
  1641. * Te "Text example"
  1642. * Nl "Line 2"
  1643. * Po 66750 53450 600 800 150 0
  1644. * From 24 1 0 Italic
  1645. * $EndTEXTPCB
  1646. * Nl "line nn" is a line added to the current text
  1647. */
  1648. int TEXTE_PCB::ReadTextePcbDescr( LINE_READER* aReader )
  1649. {
  1650. char* line;
  1651. char text[1024];
  1652. char style[256];
  1653. while( aReader->ReadLine() )
  1654. {
  1655. line = aReader->Line();
  1656. if( strnicmp( line, "$EndTEXTPCB", 11 ) == 0 )
  1657. return 0;
  1658. if( strncmp( line, "Te", 2 ) == 0 ) // Text line (first line for multi line texts
  1659. {
  1660. ReadDelimitedText( text, line + 2, sizeof(text) );
  1661. m_Text = FROM_UTF8( text );
  1662. continue;
  1663. }
  1664. if( strncmp( line, "nl", 2 ) == 0 ) // next line of the current text
  1665. {
  1666. ReadDelimitedText( text, line + 2, sizeof(text) );
  1667. m_Text.Append( '\n' );
  1668. m_Text += FROM_UTF8( text );
  1669. continue;
  1670. }
  1671. if( strncmp( line, "Po", 2 ) == 0 )
  1672. {
  1673. double angle;
  1674. sscanf( line + 2, " %d %d %d %d %d %lf",
  1675. &m_Pos.x, &m_Pos.y, &m_Size.x, &m_Size.y,
  1676. &m_Thickness, &angle );
  1677. SetOrientation( angle );
  1678. // Ensure the text has minimal size to see this text on screen:
  1679. if( m_Size.x < 5 )
  1680. m_Size.x = 5;
  1681. if( m_Size.y < 5 )
  1682. m_Size.y = 5;
  1683. continue;
  1684. }
  1685. if( strncmp( line, "De", 2 ) == 0 )
  1686. {
  1687. style[0] = 0;
  1688. int normal_display = 1;
  1689. char hJustify = 'c';
  1690. sscanf( line + 2, " %d %d %lX %s %c\n", &m_Layer, &normal_display,
  1691. &m_TimeStamp, style, &hJustify );
  1692. m_Mirror = normal_display ? false : true;
  1693. if( m_Layer < FIRST_COPPER_LAYER )
  1694. m_Layer = FIRST_COPPER_LAYER;
  1695. if( m_Layer > LAST_NO_COPPER_LAYER )
  1696. m_Layer = LAST_NO_COPPER_LAYER;
  1697. if( strnicmp( style, "Italic", 6 ) == 0 )
  1698. m_Italic = 1;
  1699. else
  1700. m_Italic = 0;
  1701. switch( hJustify )
  1702. {
  1703. case 'l':
  1704. case 'L':
  1705. m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
  1706. break;
  1707. case 'c':
  1708. case 'C':
  1709. m_HJustify = GR_TEXT_HJUSTIFY_CENTER;
  1710. break;
  1711. case 'r':
  1712. case 'R':
  1713. m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
  1714. break;
  1715. default:
  1716. m_HJustify = GR_TEXT_HJUSTIFY_CENTER;
  1717. break;
  1718. }
  1719. continue;
  1720. }
  1721. }
  1722. // Set a reasonable width:
  1723. if( m_Thickness < 1 )
  1724. m_Thickness = 1;
  1725. m_Thickness = Clamp_Text_PenSize( m_Thickness, m_Size );
  1726. return 1;
  1727. }
  1728. /**
  1729. * Function ReadDescr
  1730. * Read description from a given line in "*.brd" format.
  1731. * @param aReader The line reader object which contains the first line of description.
  1732. * @return int - > 0 if success reading else 0.
  1733. */
  1734. int TEXTE_MODULE::ReadDescr( LINE_READER* aReader )
  1735. {
  1736. int success = true;
  1737. int type;
  1738. char BufCar1[128], BufCar2[128], BufCar3[128];
  1739. char* line = aReader->Line();
  1740. double angle;
  1741. int layer = SILKSCREEN_N_FRONT;
  1742. BufCar1[0] = 0;
  1743. BufCar2[0] = 0;
  1744. BufCar3[0] = 0;
  1745. if( sscanf( line + 1, "%d %d %d %d %d %lf %d %s %s %d %s",
  1746. &type,
  1747. &m_Pos0.x, &m_Pos0.y,
  1748. &m_Size.y, &m_Size.x,
  1749. &angle, &m_Thickness,
  1750. BufCar1, BufCar2, &layer, BufCar3 ) >= 10 )
  1751. {
  1752. success = true;
  1753. SetOrientation( angle );
  1754. }
  1755. if( (type != TEXT_is_REFERENCE) && (type != TEXT_is_VALUE) )
  1756. type = TEXT_is_DIVERS;
  1757. m_Type = type;
  1758. // Due to the Pcbnew history, .m_Orient is saved in screen value
  1759. // but it is handled as relative to its parent footprint
  1760. m_Orient -= ( (MODULE*) m_Parent )->m_Orient;
  1761. if( BufCar1[0] == 'M' )
  1762. m_Mirror = true;
  1763. else
  1764. m_Mirror = false;
  1765. if( BufCar2[0] == 'I' )
  1766. m_NoShow = true;
  1767. else
  1768. m_NoShow = false;
  1769. if( BufCar3[0] == 'I' )
  1770. m_Italic = true;
  1771. else
  1772. m_Italic = false;
  1773. // Test for a reasonable layer:
  1774. if( layer < 0 )
  1775. layer = 0;
  1776. if( layer > LAST_NO_COPPER_LAYER )
  1777. layer = LAST_NO_COPPER_LAYER;
  1778. if( layer == LAYER_N_BACK )
  1779. layer = SILKSCREEN_N_BACK;
  1780. else if( layer == LAYER_N_FRONT )
  1781. layer = SILKSCREEN_N_FRONT;
  1782. SetLayer( layer );
  1783. // Calculate the actual position.
  1784. SetDrawCoord();
  1785. // Search and read the "text" string (a quoted text).
  1786. ReadDelimitedText( &m_Text, line );
  1787. // Test for a reasonable size:
  1788. if( m_Size.x < TEXTS_MIN_SIZE )
  1789. m_Size.x = TEXTS_MIN_SIZE;
  1790. if( m_Size.y < TEXTS_MIN_SIZE )
  1791. m_Size.y = TEXTS_MIN_SIZE;
  1792. // Set a reasonable width:
  1793. if( m_Thickness < 1 )
  1794. m_Thickness = 1;
  1795. m_Thickness = Clamp_Text_PenSize( m_Thickness, m_Size );
  1796. return success;
  1797. }
  1798. #endif // USE_NEW_PCBNEW_LOAD