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.

626 lines
22 KiB

12 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  19. * or you may search the http://www.gnu.org website for the version 2 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. #include <board_design_settings.h>
  24. #include <convert_to_biu.h>
  25. #include <layers_id_colors_and_visibility.h>
  26. #include <macros.h>
  27. #include <math/util.h> // for KiROUND
  28. #include <pcb_plot_params.h>
  29. #include <pcb_plot_params_parser.h>
  30. #include <plotter.h>
  31. #include <settings/color_settings.h>
  32. #define PLOT_LINEWIDTH_DEFAULT ( DEFAULT_TEXT_WIDTH * IU_PER_MM )
  33. #define HPGL_PEN_DIAMETER_MIN 0
  34. #define HPGL_PEN_DIAMETER_MAX 100.0 // Unit = mil
  35. #define HPGL_PEN_SPEED_MIN 1 // this param is always in cm/s
  36. #define HPGL_PEN_SPEED_MAX 99 // this param is always in cm/s
  37. #define HPGL_PEN_NUMBER_MIN 1
  38. #define HPGL_PEN_NUMBER_MAX 16
  39. #define SVG_PRECISION_MIN 3U
  40. #define SVG_PRECISION_MAX 6U
  41. #define SVG_PRECISION_DEFAULT 6
  42. // default trailing digits in Gerber coordinates, when units are mm
  43. // This is also the max usable precision (i.e. internal Pcbnew Units)
  44. static const int gbrDefaultPrecision = 6;
  45. using namespace PCBPLOTPARAMS_T;
  46. static const char* getTokenName( T aTok )
  47. {
  48. return PCB_PLOT_PARAMS_LEXER::TokenName( aTok );
  49. }
  50. static bool setInt( int* aTarget, int aValue, int aMin, int aMax )
  51. {
  52. int temp = aValue;
  53. if( aValue < aMin )
  54. temp = aMin;
  55. else if( aValue > aMax )
  56. temp = aMax;
  57. *aTarget = temp;
  58. return (temp == aValue);
  59. }
  60. static bool setDouble( double* aTarget, double aValue, double aMin, double aMax )
  61. {
  62. double temp = aValue;
  63. if( aValue < aMin )
  64. temp = aMin;
  65. else if( aValue > aMax )
  66. temp = aMax;
  67. *aTarget = temp;
  68. return (temp == aValue);
  69. }
  70. // PCB_PLOT_PARAMS
  71. PCB_PLOT_PARAMS::PCB_PLOT_PARAMS()
  72. {
  73. m_useGerberProtelExtensions = false;
  74. m_gerberDisableApertMacros = false;
  75. m_useGerberX2format = true;
  76. m_includeGerberNetlistInfo = true;
  77. m_createGerberJobFile = true;
  78. m_gerberPrecision = gbrDefaultPrecision;
  79. // we used 0.1mils for SVG step before, but nm precision is more accurate, so we use nm
  80. m_svgPrecision = SVG_PRECISION_DEFAULT;
  81. m_svgUseInch = false;
  82. m_excludeEdgeLayer = true;
  83. m_plotFrameRef = false;
  84. m_plotViaOnMaskLayer = false;
  85. m_plotMode = FILLED;
  86. m_DXFplotPolygonMode = true;
  87. m_DXFplotUnits = DXF_UNITS::INCHES;
  88. m_useAuxOrigin = false;
  89. m_HPGLPenNum = 1;
  90. m_HPGLPenSpeed = 20; // this param is always in cm/s
  91. m_HPGLPenDiam = 15; // in mils
  92. m_negative = false;
  93. m_A4Output = false;
  94. m_plotReference = true;
  95. m_plotValue = true;
  96. m_plotInvisibleText = false;
  97. m_sketchPadsOnFabLayers = false;
  98. m_subtractMaskFromSilk = false;
  99. m_format = PLOT_FORMAT::GERBER;
  100. m_mirror = false;
  101. m_drillMarks = SMALL_DRILL_SHAPE;
  102. m_autoScale = false;
  103. m_scale = 1.0;
  104. m_scaleSelection = 1;
  105. m_fineScaleAdjustX = 1.0;
  106. m_fineScaleAdjustY = 1.0;
  107. m_widthAdjust = 0.;
  108. m_textMode = PLOT_TEXT_MODE::DEFAULT;
  109. m_outputDirectory.clear();
  110. m_layerSelection = LSET( 7, F_SilkS, B_SilkS, F_Mask, B_Mask,
  111. F_Paste, B_Paste, Edge_Cuts )
  112. | LSET::AllCuMask();
  113. // This parameter controls if the NPTH pads will be plotted or not
  114. // it is a "local" parameter
  115. m_skipNPTH_Pads = false;
  116. m_sketchPadLineWidth = Millimeter2iu( 0.1 ); // line width to plot items in outline mode
  117. m_default_colors = std::make_shared<COLOR_SETTINGS>();
  118. m_colors = m_default_colors.get();
  119. }
  120. void PCB_PLOT_PARAMS::SetGerberPrecision( int aPrecision )
  121. {
  122. // Currently geber files use mm.
  123. // accepted precision is only 6 (max value, this is the resolution of Pcbnew)
  124. // or 5, min value for professional boards, when 6 creates problems
  125. // to board makers.
  126. m_gerberPrecision = aPrecision == gbrDefaultPrecision-1 ? gbrDefaultPrecision-1 :
  127. gbrDefaultPrecision;
  128. }
  129. void PCB_PLOT_PARAMS::SetSvgPrecision( unsigned aPrecision, bool aUseInch )
  130. {
  131. m_svgUseInch = aUseInch;
  132. m_svgPrecision = Clamp( SVG_PRECISION_MIN, aPrecision, SVG_PRECISION_MAX );
  133. }
  134. // PLEASE NOTE: only plot dialog options are processed
  135. void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter,
  136. int aNestLevel, int aControl ) const
  137. {
  138. const char* falseStr = getTokenName( T_false );
  139. const char* trueStr = getTokenName( T_true );
  140. aFormatter->Print( aNestLevel, "(%s\n", getTokenName( T_pcbplotparams ) );
  141. aFormatter->Print( aNestLevel+1, "(%s 0x%s)\n", getTokenName( T_layerselection ),
  142. m_layerSelection.FmtHex().c_str() );
  143. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_disableapertmacros ),
  144. m_gerberDisableApertMacros ? trueStr : falseStr );
  145. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberextensions ),
  146. m_useGerberProtelExtensions ? trueStr : falseStr );
  147. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberattributes ),
  148. GetUseGerberX2format() ? trueStr : falseStr );
  149. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberadvancedattributes ),
  150. GetIncludeGerberNetlistInfo() ? trueStr : falseStr );
  151. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_creategerberjobfile ),
  152. GetCreateGerberJobFile() ? trueStr : falseStr );
  153. if( m_gerberPrecision != gbrDefaultPrecision ) // save this option only if it is not the default value,
  154. // to avoid incompatibility with older Pcbnew version
  155. aFormatter->Print( aNestLevel+1, "(%s %d)\n",
  156. getTokenName( T_gerberprecision ), m_gerberPrecision );
  157. // SVG options
  158. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_svguseinch ),
  159. m_svgUseInch ? trueStr : falseStr );
  160. aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_svgprecision ),
  161. m_svgPrecision );
  162. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_excludeedgelayer ),
  163. m_excludeEdgeLayer ? trueStr : falseStr );
  164. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_plotframeref ),
  165. m_plotFrameRef ? trueStr : falseStr );
  166. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_viasonmask ),
  167. m_plotViaOnMaskLayer ? trueStr : falseStr );
  168. aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_mode ),
  169. GetPlotMode() == SKETCH ? 2 : 1 ); // Value 0 (LINE mode) no more used
  170. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_useauxorigin ),
  171. m_useAuxOrigin ? trueStr : falseStr );
  172. // HPGL options
  173. aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_hpglpennumber ),
  174. m_HPGLPenNum );
  175. aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_hpglpenspeed ),
  176. m_HPGLPenSpeed );
  177. aFormatter->Print( aNestLevel+1, "(%s %f)\n", getTokenName( T_hpglpendiameter ),
  178. m_HPGLPenDiam );
  179. // DXF options
  180. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_dxfpolygonmode ),
  181. m_DXFplotPolygonMode ? trueStr : falseStr );
  182. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_dxfimperialunits ),
  183. m_DXFplotUnits == DXF_UNITS::INCHES ? trueStr : falseStr );
  184. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_dxfusepcbnewfont ),
  185. m_textMode == PLOT_TEXT_MODE::NATIVE ? falseStr : trueStr );
  186. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_psnegative ),
  187. m_negative ? trueStr : falseStr );
  188. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_psa4output ),
  189. m_A4Output ? trueStr : falseStr );
  190. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_plotreference ),
  191. m_plotReference ? trueStr : falseStr );
  192. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_plotvalue ),
  193. m_plotValue ? trueStr : falseStr );
  194. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_plotinvisibletext ),
  195. m_plotInvisibleText ? trueStr : falseStr );
  196. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_sketchpadsonfab ),
  197. m_sketchPadsOnFabLayers ? trueStr : falseStr );
  198. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_subtractmaskfromsilk ),
  199. m_subtractMaskFromSilk ? trueStr : falseStr );
  200. aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_outputformat ),
  201. static_cast<int>( m_format ) );
  202. aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_mirror ),
  203. m_mirror ? trueStr : falseStr );
  204. aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_drillshape ),
  205. m_drillMarks );
  206. aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_scaleselection ),
  207. m_scaleSelection );
  208. aFormatter->Print( aNestLevel+1, "(%s \"%s\")", getTokenName( T_outputdirectory ),
  209. (const char*) m_outputDirectory.utf8_str() );
  210. aFormatter->Print( 0, "\n" );
  211. aFormatter->Print( aNestLevel, ")\n" );
  212. }
  213. void PCB_PLOT_PARAMS::Parse( PCB_PLOT_PARAMS_PARSER* aParser )
  214. {
  215. aParser->Parse( this );
  216. }
  217. bool PCB_PLOT_PARAMS::IsSameAs( const PCB_PLOT_PARAMS &aPcbPlotParams ) const
  218. {
  219. if( m_layerSelection != aPcbPlotParams.m_layerSelection )
  220. return false;
  221. if( m_useGerberProtelExtensions != aPcbPlotParams.m_useGerberProtelExtensions )
  222. return false;
  223. if( m_gerberDisableApertMacros != aPcbPlotParams.m_gerberDisableApertMacros )
  224. return false;
  225. if( m_useGerberX2format != aPcbPlotParams.m_useGerberX2format )
  226. return false;
  227. if( m_includeGerberNetlistInfo != aPcbPlotParams.m_includeGerberNetlistInfo )
  228. return false;
  229. if( m_createGerberJobFile != aPcbPlotParams.m_createGerberJobFile )
  230. return false;
  231. if( m_gerberPrecision != aPcbPlotParams.m_gerberPrecision )
  232. return false;
  233. if( m_excludeEdgeLayer != aPcbPlotParams.m_excludeEdgeLayer )
  234. return false;
  235. if( m_plotFrameRef != aPcbPlotParams.m_plotFrameRef )
  236. return false;
  237. if( m_plotViaOnMaskLayer != aPcbPlotParams.m_plotViaOnMaskLayer )
  238. return false;
  239. if( m_plotMode != aPcbPlotParams.m_plotMode )
  240. return false;
  241. if( m_DXFplotPolygonMode != aPcbPlotParams.m_DXFplotPolygonMode )
  242. return false;
  243. if( m_DXFplotUnits != aPcbPlotParams.m_DXFplotUnits )
  244. return false;
  245. if( m_svgPrecision != aPcbPlotParams.m_svgPrecision )
  246. return false;
  247. if( m_svgUseInch != aPcbPlotParams.m_svgUseInch )
  248. return false;
  249. if( m_useAuxOrigin != aPcbPlotParams.m_useAuxOrigin )
  250. return false;
  251. if( m_HPGLPenNum != aPcbPlotParams.m_HPGLPenNum )
  252. return false;
  253. if( m_HPGLPenSpeed != aPcbPlotParams.m_HPGLPenSpeed )
  254. return false;
  255. if( m_HPGLPenDiam != aPcbPlotParams.m_HPGLPenDiam )
  256. return false;
  257. if( m_negative != aPcbPlotParams.m_negative )
  258. return false;
  259. if( m_A4Output != aPcbPlotParams.m_A4Output )
  260. return false;
  261. if( m_plotReference != aPcbPlotParams.m_plotReference )
  262. return false;
  263. if( m_plotValue != aPcbPlotParams.m_plotValue )
  264. return false;
  265. if( m_plotInvisibleText != aPcbPlotParams.m_plotInvisibleText )
  266. return false;
  267. if( m_sketchPadsOnFabLayers != aPcbPlotParams.m_sketchPadsOnFabLayers )
  268. return false;
  269. if( m_subtractMaskFromSilk != aPcbPlotParams.m_subtractMaskFromSilk )
  270. return false;
  271. if( m_format != aPcbPlotParams.m_format )
  272. return false;
  273. if( m_mirror != aPcbPlotParams.m_mirror )
  274. return false;
  275. if( m_drillMarks != aPcbPlotParams.m_drillMarks )
  276. return false;
  277. if( m_scaleSelection != aPcbPlotParams.m_scaleSelection )
  278. return false;
  279. if( m_autoScale != aPcbPlotParams.m_autoScale )
  280. return false;
  281. if( m_scale != aPcbPlotParams.m_scale )
  282. return false;
  283. if( m_fineScaleAdjustX != aPcbPlotParams.m_fineScaleAdjustX )
  284. return false;
  285. if( m_fineScaleAdjustY != aPcbPlotParams.m_fineScaleAdjustY )
  286. return false;
  287. if( m_widthAdjust != aPcbPlotParams.m_widthAdjust )
  288. return false;
  289. if( m_textMode != aPcbPlotParams.m_textMode )
  290. return false;
  291. if( !m_outputDirectory.IsSameAs( aPcbPlotParams.m_outputDirectory ) )
  292. return false;
  293. return true;
  294. }
  295. bool PCB_PLOT_PARAMS::SetHPGLPenDiameter( double aValue )
  296. {
  297. return setDouble( &m_HPGLPenDiam, aValue, HPGL_PEN_DIAMETER_MIN, HPGL_PEN_DIAMETER_MAX );
  298. }
  299. bool PCB_PLOT_PARAMS::SetHPGLPenSpeed( int aValue )
  300. {
  301. return setInt( &m_HPGLPenSpeed, aValue, HPGL_PEN_SPEED_MIN, HPGL_PEN_SPEED_MAX );
  302. }
  303. // PCB_PLOT_PARAMS_PARSER
  304. PCB_PLOT_PARAMS_PARSER::PCB_PLOT_PARAMS_PARSER( LINE_READER* aReader ) :
  305. PCB_PLOT_PARAMS_LEXER( aReader )
  306. {
  307. }
  308. PCB_PLOT_PARAMS_PARSER::PCB_PLOT_PARAMS_PARSER( char* aLine, const wxString& aSource ) :
  309. PCB_PLOT_PARAMS_LEXER( aLine, aSource )
  310. {
  311. }
  312. void PCB_PLOT_PARAMS_PARSER::Parse( PCB_PLOT_PARAMS* aPcbPlotParams )
  313. {
  314. T token;
  315. while( ( token = NextTok() ) != T_RIGHT )
  316. {
  317. if( token == T_EOF)
  318. Unexpected( T_EOF );
  319. if( token == T_LEFT )
  320. token = NextTok();
  321. if( token == T_pcbplotparams )
  322. continue;
  323. bool skip_right = false;
  324. switch( token )
  325. {
  326. case T_layerselection:
  327. {
  328. token = NeedSYMBOLorNUMBER();
  329. const std::string& cur = CurStr();
  330. if( token == T_NUMBER ) // pretty 3 format had legacy Cu stack.
  331. {
  332. // It's not possible to convert a legacy Cu layer number to a new Cu layer
  333. // number without knowing the number or total Cu layers in the legacy board.
  334. // We do not have that information here, so simply set all layers ON. User
  335. // can turn them off in the UI.
  336. aPcbPlotParams->m_layerSelection = LSET( 2, F_SilkS, B_SilkS)
  337. | LSET::AllCuMask();
  338. }
  339. else if( cur.find_first_of( "0x" ) == 0 ) // pretty ver. 4.
  340. {
  341. // skip the leading 2 0x bytes.
  342. aPcbPlotParams->m_layerSelection.ParseHex( cur.c_str()+2, cur.size()-2 );
  343. }
  344. else
  345. Expecting( "integer or hex layerSelection" );
  346. }
  347. break;
  348. case T_disableapertmacros:
  349. aPcbPlotParams->m_gerberDisableApertMacros = parseBool();
  350. break;
  351. case T_usegerberextensions:
  352. aPcbPlotParams->m_useGerberProtelExtensions = parseBool();
  353. break;
  354. case T_usegerberattributes:
  355. aPcbPlotParams->m_useGerberX2format = parseBool();
  356. break;
  357. case T_usegerberadvancedattributes:
  358. aPcbPlotParams->m_includeGerberNetlistInfo = parseBool();
  359. break;
  360. case T_creategerberjobfile:
  361. aPcbPlotParams->m_createGerberJobFile = parseBool();
  362. break;
  363. case T_gerberprecision:
  364. aPcbPlotParams->m_gerberPrecision = parseInt( gbrDefaultPrecision-1,
  365. gbrDefaultPrecision);
  366. break;
  367. case T_svgprecision:
  368. aPcbPlotParams->m_svgPrecision = parseInt( SVG_PRECISION_MIN, SVG_PRECISION_MAX );
  369. break;
  370. case T_svguseinch:
  371. aPcbPlotParams->m_svgUseInch = parseBool();
  372. break;
  373. case T_psa4output:
  374. aPcbPlotParams->m_A4Output = parseBool();
  375. break;
  376. case T_excludeedgelayer:
  377. aPcbPlotParams->m_excludeEdgeLayer = parseBool();
  378. break;
  379. case T_plotframeref:
  380. aPcbPlotParams->m_plotFrameRef = parseBool();
  381. break;
  382. case T_viasonmask:
  383. aPcbPlotParams->m_plotViaOnMaskLayer = parseBool();
  384. break;
  385. case T_mode:
  386. aPcbPlotParams->SetPlotMode( parseInt( 0, 2 ) > 1 ? SKETCH : FILLED );
  387. break;
  388. case T_useauxorigin:
  389. aPcbPlotParams->m_useAuxOrigin = parseBool();
  390. break;
  391. case T_hpglpennumber:
  392. aPcbPlotParams->m_HPGLPenNum = parseInt( HPGL_PEN_NUMBER_MIN,
  393. HPGL_PEN_NUMBER_MAX );
  394. break;
  395. case T_hpglpenspeed:
  396. aPcbPlotParams->m_HPGLPenSpeed = parseInt( HPGL_PEN_SPEED_MIN,
  397. HPGL_PEN_SPEED_MAX );
  398. break;
  399. case T_hpglpendiameter:
  400. aPcbPlotParams->m_HPGLPenDiam = parseDouble();
  401. break;
  402. case T_hpglpenoverlay:
  403. // No more used. juste here for compatibility with old versions
  404. parseInt( 0, HPGL_PEN_DIAMETER_MAX );
  405. break;
  406. case T_dxfpolygonmode:
  407. aPcbPlotParams->m_DXFplotPolygonMode = parseBool();
  408. break;
  409. case T_dxfimperialunits:
  410. aPcbPlotParams->m_DXFplotUnits = parseBool() ? DXF_UNITS::INCHES
  411. : DXF_UNITS::MILLIMETERS;
  412. break;
  413. case T_dxfusepcbnewfont:
  414. aPcbPlotParams->m_textMode = parseBool() ? PLOT_TEXT_MODE::DEFAULT
  415. : PLOT_TEXT_MODE::NATIVE;
  416. break;
  417. case T_pscolor:
  418. NeedSYMBOL(); // This actually was never used...
  419. break;
  420. case T_psnegative:
  421. aPcbPlotParams->m_negative = parseBool();
  422. break;
  423. case T_plotreference:
  424. aPcbPlotParams->m_plotReference = parseBool();
  425. break;
  426. case T_plotvalue:
  427. aPcbPlotParams->m_plotValue = parseBool();
  428. break;
  429. case T_plotinvisibletext:
  430. aPcbPlotParams->m_plotInvisibleText = parseBool();
  431. break;
  432. case T_sketchpadsonfab:
  433. aPcbPlotParams->m_sketchPadsOnFabLayers= parseBool();
  434. break;
  435. case T_subtractmaskfromsilk:
  436. aPcbPlotParams->m_subtractMaskFromSilk = parseBool();
  437. break;
  438. case T_outputformat:
  439. aPcbPlotParams->m_format = static_cast<PLOT_FORMAT>(
  440. parseInt( static_cast<int>( PLOT_FORMAT::FIRST_FORMAT ),
  441. static_cast<int>( PLOT_FORMAT::LAST_FORMAT ) ) );
  442. break;
  443. case T_mirror:
  444. aPcbPlotParams->m_mirror = parseBool();
  445. break;
  446. case T_drillshape:
  447. aPcbPlotParams->m_drillMarks = static_cast<PCB_PLOT_PARAMS::DrillMarksType>
  448. ( parseInt( 0, 2 ) );
  449. break;
  450. case T_scaleselection:
  451. aPcbPlotParams->m_scaleSelection = parseInt( 0, 4 );
  452. break;
  453. case T_outputdirectory:
  454. NeedSYMBOLorNUMBER(); // a dir name can be like a number
  455. aPcbPlotParams->m_outputDirectory = FROM_UTF8( CurText() );
  456. break;
  457. default:
  458. skipCurrent(); // skip unknown or outdated plot parameter
  459. skip_right = true; // the closing right token is already read.
  460. break;
  461. }
  462. if( ! skip_right )
  463. NeedRIGHT();
  464. }
  465. }
  466. bool PCB_PLOT_PARAMS_PARSER::parseBool()
  467. {
  468. T token = NeedSYMBOL();
  469. if( token != T_false && token != T_true )
  470. Expecting( "true|false" );
  471. return token == T_true;
  472. }
  473. int PCB_PLOT_PARAMS_PARSER::parseInt( int aMin, int aMax )
  474. {
  475. T token = NextTok();
  476. if( token != T_NUMBER )
  477. Expecting( T_NUMBER );
  478. int val = atoi( CurText() );
  479. if( val < aMin )
  480. val = aMin;
  481. else if( val > aMax )
  482. val = aMax;
  483. return val;
  484. }
  485. double PCB_PLOT_PARAMS_PARSER::parseDouble()
  486. {
  487. T token = NextTok();
  488. if( token != T_NUMBER )
  489. Expecting( T_NUMBER );
  490. double val = strtod( CurText(), NULL );
  491. return val;
  492. }
  493. void PCB_PLOT_PARAMS_PARSER::skipCurrent()
  494. {
  495. int curr_level = 0;
  496. T token;
  497. while( ( token = NextTok() ) != T_EOF )
  498. {
  499. if( token == T_LEFT )
  500. curr_level--;
  501. if( token == T_RIGHT )
  502. {
  503. curr_level++;
  504. if( curr_level > 0 )
  505. return;
  506. }
  507. }
  508. }