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.

864 lines
26 KiB

10 months ago
12 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright The 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 <charconv>
  25. #include <layer_ids.h>
  26. #include <lset.h>
  27. #include <string_utils.h>
  28. #include <pcb_plot_params.h>
  29. #include <pcb_plot_params_parser.h>
  30. #include <plotters/plotter.h>
  31. #include <io/kicad/kicad_io_utils.h>
  32. #include <settings/color_settings.h>
  33. #include <lseq.h>
  34. #define PLOT_LINEWIDTH_DEFAULT ( DEFAULT_TEXT_WIDTH * IU_PER_MM )
  35. #define SVG_PRECISION_MIN 3U
  36. #define SVG_PRECISION_MAX 6U
  37. #define SVG_PRECISION_DEFAULT 4
  38. // default trailing digits in Gerber coordinates, when units are mm
  39. // This is also the max usable precision (i.e. internal Pcbnew Units)
  40. static const int gbrDefaultPrecision = 6;
  41. using namespace PCBPLOTPARAMS_T;
  42. static const char* getTokenName( T aTok )
  43. {
  44. return PCB_PLOT_PARAMS_LEXER::TokenName( aTok );
  45. }
  46. PCB_PLOT_PARAMS::PCB_PLOT_PARAMS()
  47. {
  48. m_useGerberProtelExtensions = false;
  49. m_gerberDisableApertMacros = false;
  50. m_useGerberX2format = true;
  51. m_includeGerberNetlistInfo = true;
  52. m_createGerberJobFile = true;
  53. m_gerberPrecision = gbrDefaultPrecision;
  54. m_dashedLineDashRatio = 12.0; // From ISO 128-2
  55. m_dashedLineGapRatio = 3.0; // From ISO 128-2
  56. // we used 0.1mils for SVG step before, but nm precision is more accurate, so we use nm
  57. m_svgPrecision = SVG_PRECISION_DEFAULT;
  58. m_svgFitPageToBoard = false;
  59. m_plotDrawingSheet = false;
  60. m_plotMode = FILLED;
  61. m_DXFPolygonMode = true;
  62. m_DXFUnits = DXF_UNITS::INCH;
  63. m_useAuxOrigin = false;
  64. m_negative = false;
  65. m_A4Output = false;
  66. m_plotReference = true;
  67. m_plotValue = true;
  68. m_plotFPText = true;
  69. m_sketchPadsOnFabLayers = false;
  70. m_hideDNPFPsOnFabLayers = false;
  71. m_sketchDNPFPsOnFabLayers = true;
  72. m_crossoutDNPFPsOnFabLayers = true;
  73. m_plotPadNumbers = false;
  74. m_subtractMaskFromSilk = false;
  75. m_format = PLOT_FORMAT::GERBER;
  76. m_mirror = false;
  77. m_drillMarks = DRILL_MARKS::SMALL_DRILL_SHAPE;
  78. m_autoScale = false;
  79. m_scale = 1.0;
  80. m_scaleSelection = 1;
  81. m_fineScaleAdjustX = 1.0;
  82. m_fineScaleAdjustY = 1.0;
  83. m_widthAdjust = 0.;
  84. m_textMode = PLOT_TEXT_MODE::DEFAULT;
  85. m_outputDirectory.clear();
  86. m_layerSelection = LSET( { F_SilkS, B_SilkS, F_Mask, B_Mask,
  87. F_Paste, B_Paste, Edge_Cuts } )
  88. | LSET::AllCuMask();
  89. m_PDFFrontFPPropertyPopups = true;
  90. m_PDFBackFPPropertyPopups = true;
  91. m_PDFMetadata = true;
  92. m_PDFSingle = false;
  93. // This parameter controls if the NPTH pads will be plotted or not
  94. // it is a "local" parameter
  95. m_skipNPTH_Pads = false;
  96. // line width to plot items in outline mode.
  97. m_sketchPadLineWidth = pcbIUScale.mmToIU( 0.1 );
  98. m_default_colors = std::make_shared<COLOR_SETTINGS>();
  99. m_colors = m_default_colors.get();
  100. m_blackAndWhite = true;
  101. }
  102. void PCB_PLOT_PARAMS::SetGerberPrecision( int aPrecision )
  103. {
  104. // Currently Gerber files use mm.
  105. // accepted precision is only 6 (max value, this is the resolution of Pcbnew)
  106. // or 5, min value for professional boards, when 6 creates problems
  107. // to board makers.
  108. m_gerberPrecision = aPrecision == gbrDefaultPrecision-1 ? gbrDefaultPrecision-1 :
  109. gbrDefaultPrecision;
  110. }
  111. void PCB_PLOT_PARAMS::SetSvgPrecision( unsigned aPrecision )
  112. {
  113. m_svgPrecision = std::clamp( aPrecision, SVG_PRECISION_MIN, SVG_PRECISION_MAX );
  114. }
  115. void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter ) const
  116. {
  117. aFormatter->Print( "(pcbplotparams" );
  118. aFormatter->Print( "(layerselection 0x%s)", m_layerSelection.FmtHex().c_str() );
  119. LSET commonLayers;
  120. for( PCB_LAYER_ID commonLayer : m_plotOnAllLayersSequence )
  121. commonLayers.set( commonLayer );
  122. aFormatter->Print( "(plot_on_all_layers_selection 0x%s)", commonLayers.FmtHex().c_str() );
  123. KICAD_FORMAT::FormatBool( aFormatter, "disableapertmacros", m_gerberDisableApertMacros );
  124. KICAD_FORMAT::FormatBool( aFormatter, "usegerberextensions", m_useGerberProtelExtensions );
  125. KICAD_FORMAT::FormatBool( aFormatter, "usegerberattributes", GetUseGerberX2format() );
  126. KICAD_FORMAT::FormatBool( aFormatter, "usegerberadvancedattributes", GetIncludeGerberNetlistInfo() );
  127. KICAD_FORMAT::FormatBool( aFormatter, "creategerberjobfile", GetCreateGerberJobFile() );
  128. // save this option only if it is not the default value,
  129. // to avoid incompatibility with older Pcbnew version
  130. if( m_gerberPrecision != gbrDefaultPrecision )
  131. aFormatter->Print( "(gerberprecision %d)", m_gerberPrecision );
  132. aFormatter->Print( "(dashed_line_dash_ratio %f)", GetDashedLineDashRatio() );
  133. aFormatter->Print( "(dashed_line_gap_ratio %f)", GetDashedLineGapRatio() );
  134. // SVG options
  135. aFormatter->Print( "(svgprecision %d)", m_svgPrecision );
  136. KICAD_FORMAT::FormatBool( aFormatter, "plotframeref", m_plotDrawingSheet );
  137. aFormatter->Print( "(mode %d)", GetPlotMode() == SKETCH ? 2 : 1 );
  138. KICAD_FORMAT::FormatBool( aFormatter, "useauxorigin", m_useAuxOrigin );
  139. // PDF options
  140. KICAD_FORMAT::FormatBool( aFormatter, getTokenName( T_pdf_front_fp_property_popups ),
  141. m_PDFFrontFPPropertyPopups );
  142. KICAD_FORMAT::FormatBool( aFormatter, getTokenName( T_pdf_back_fp_property_popups ),
  143. m_PDFBackFPPropertyPopups );
  144. KICAD_FORMAT::FormatBool( aFormatter, getTokenName( T_pdf_metadata ), m_PDFMetadata );
  145. KICAD_FORMAT::FormatBool( aFormatter, getTokenName( T_pdf_single_document ), m_PDFSingle );
  146. // DXF options
  147. KICAD_FORMAT::FormatBool( aFormatter, getTokenName( T_dxfpolygonmode ), m_DXFPolygonMode );
  148. KICAD_FORMAT::FormatBool( aFormatter, getTokenName( T_dxfimperialunits ),
  149. m_DXFUnits == DXF_UNITS::INCH );
  150. KICAD_FORMAT::FormatBool( aFormatter, getTokenName( T_dxfusepcbnewfont ),
  151. m_textMode != PLOT_TEXT_MODE::NATIVE );
  152. KICAD_FORMAT::FormatBool( aFormatter, getTokenName( T_psnegative ), m_negative );
  153. KICAD_FORMAT::FormatBool( aFormatter, getTokenName( T_psa4output ), m_A4Output );
  154. KICAD_FORMAT::FormatBool( aFormatter, getTokenName( T_plot_black_and_white ), m_blackAndWhite );
  155. KICAD_FORMAT::FormatBool( aFormatter, "sketchpadsonfab", m_sketchPadsOnFabLayers );
  156. KICAD_FORMAT::FormatBool( aFormatter, "plotpadnumbers", m_plotPadNumbers );
  157. KICAD_FORMAT::FormatBool( aFormatter, "hidednponfab", m_hideDNPFPsOnFabLayers );
  158. KICAD_FORMAT::FormatBool( aFormatter, "sketchdnponfab", m_sketchDNPFPsOnFabLayers );
  159. KICAD_FORMAT::FormatBool( aFormatter, "crossoutdnponfab", m_crossoutDNPFPsOnFabLayers );
  160. KICAD_FORMAT::FormatBool( aFormatter, "subtractmaskfromsilk", m_subtractMaskFromSilk );
  161. aFormatter->Print( "(outputformat %d)", static_cast<int>( m_format ) );
  162. KICAD_FORMAT::FormatBool( aFormatter, "mirror", m_mirror );
  163. aFormatter->Print( "(drillshape %d)", (int)m_drillMarks );
  164. aFormatter->Print( "(scaleselection %d)", m_scaleSelection );
  165. aFormatter->Print( "(outputdirectory %s)", aFormatter->Quotew( m_outputDirectory ).c_str() );
  166. aFormatter->Print( ")" );
  167. }
  168. void PCB_PLOT_PARAMS::Parse( PCB_PLOT_PARAMS_PARSER* aParser )
  169. {
  170. aParser->Parse( this );
  171. }
  172. bool PCB_PLOT_PARAMS::IsSameAs( const PCB_PLOT_PARAMS &aPcbPlotParams ) const
  173. {
  174. if( m_layerSelection != aPcbPlotParams.m_layerSelection )
  175. return false;
  176. if( m_plotOnAllLayersSequence != aPcbPlotParams.m_plotOnAllLayersSequence )
  177. return false;
  178. if( m_useGerberProtelExtensions != aPcbPlotParams.m_useGerberProtelExtensions )
  179. return false;
  180. if( m_gerberDisableApertMacros != aPcbPlotParams.m_gerberDisableApertMacros )
  181. return false;
  182. if( m_useGerberX2format != aPcbPlotParams.m_useGerberX2format )
  183. return false;
  184. if( m_includeGerberNetlistInfo != aPcbPlotParams.m_includeGerberNetlistInfo )
  185. return false;
  186. if( m_createGerberJobFile != aPcbPlotParams.m_createGerberJobFile )
  187. return false;
  188. if( m_gerberPrecision != aPcbPlotParams.m_gerberPrecision )
  189. return false;
  190. if( m_dashedLineDashRatio != aPcbPlotParams.m_dashedLineDashRatio )
  191. return false;
  192. if( m_dashedLineGapRatio != aPcbPlotParams.m_dashedLineGapRatio )
  193. return false;
  194. if( m_plotDrawingSheet != aPcbPlotParams.m_plotDrawingSheet )
  195. return false;
  196. if( m_plotMode != aPcbPlotParams.m_plotMode )
  197. return false;
  198. if( m_DXFPolygonMode != aPcbPlotParams.m_DXFPolygonMode )
  199. return false;
  200. if( m_DXFUnits != aPcbPlotParams.m_DXFUnits )
  201. return false;
  202. if( m_svgPrecision != aPcbPlotParams.m_svgPrecision )
  203. return false;
  204. if( m_useAuxOrigin != aPcbPlotParams.m_useAuxOrigin )
  205. return false;
  206. if( m_negative != aPcbPlotParams.m_negative )
  207. return false;
  208. if( m_PDFFrontFPPropertyPopups != aPcbPlotParams.m_PDFFrontFPPropertyPopups )
  209. return false;
  210. if( m_PDFBackFPPropertyPopups != aPcbPlotParams.m_PDFBackFPPropertyPopups )
  211. return false;
  212. if( m_PDFMetadata != aPcbPlotParams.m_PDFMetadata )
  213. return false;
  214. if( m_A4Output != aPcbPlotParams.m_A4Output )
  215. return false;
  216. if( m_plotReference != aPcbPlotParams.m_plotReference )
  217. return false;
  218. if( m_plotValue != aPcbPlotParams.m_plotValue )
  219. return false;
  220. if( m_plotFPText != aPcbPlotParams.m_plotFPText )
  221. return false;
  222. if( m_sketchPadsOnFabLayers != aPcbPlotParams.m_sketchPadsOnFabLayers )
  223. return false;
  224. if( m_plotPadNumbers != aPcbPlotParams.m_plotPadNumbers )
  225. return false;
  226. if( m_hideDNPFPsOnFabLayers != aPcbPlotParams.m_hideDNPFPsOnFabLayers )
  227. return false;
  228. if( m_sketchDNPFPsOnFabLayers != aPcbPlotParams.m_sketchDNPFPsOnFabLayers )
  229. return false;
  230. if( m_crossoutDNPFPsOnFabLayers != aPcbPlotParams.m_crossoutDNPFPsOnFabLayers )
  231. return false;
  232. if( m_subtractMaskFromSilk != aPcbPlotParams.m_subtractMaskFromSilk )
  233. return false;
  234. if( m_format != aPcbPlotParams.m_format )
  235. return false;
  236. if( m_mirror != aPcbPlotParams.m_mirror )
  237. return false;
  238. if( m_drillMarks != aPcbPlotParams.m_drillMarks )
  239. return false;
  240. if( m_scaleSelection != aPcbPlotParams.m_scaleSelection )
  241. return false;
  242. if( m_autoScale != aPcbPlotParams.m_autoScale )
  243. return false;
  244. if( m_scale != aPcbPlotParams.m_scale )
  245. return false;
  246. if( m_fineScaleAdjustX != aPcbPlotParams.m_fineScaleAdjustX )
  247. return false;
  248. if( m_fineScaleAdjustY != aPcbPlotParams.m_fineScaleAdjustY )
  249. return false;
  250. if( m_widthAdjust != aPcbPlotParams.m_widthAdjust )
  251. return false;
  252. if( m_textMode != aPcbPlotParams.m_textMode )
  253. return false;
  254. if( m_blackAndWhite != aPcbPlotParams.m_blackAndWhite )
  255. return false;
  256. if( !m_outputDirectory.IsSameAs( aPcbPlotParams.m_outputDirectory ) )
  257. return false;
  258. return true;
  259. }
  260. PCB_PLOT_PARAMS_PARSER::PCB_PLOT_PARAMS_PARSER( LINE_READER* aReader, int aBoardFileVersion ) :
  261. PCB_PLOT_PARAMS_LEXER( aReader ),
  262. m_boardFileVersion( aBoardFileVersion )
  263. {
  264. }
  265. PCB_PLOT_PARAMS_PARSER::PCB_PLOT_PARAMS_PARSER( char* aLine, const wxString& aSource ) :
  266. PCB_PLOT_PARAMS_LEXER( aLine, aSource ),
  267. m_boardFileVersion( 0 )
  268. {
  269. }
  270. /**
  271. * These are the layer IDs from before 5e0abadb23425765e164f49ee2f893e94ddb97fc,
  272. * and are needed for mapping old PCB files to the new layer numbering.
  273. */
  274. enum LEGACY_PCB_LAYER_ID: int
  275. {
  276. LEGACY_UNDEFINED_LAYER = -1,
  277. LEGACY_UNSELECTED_LAYER = -2,
  278. LEGACY_F_Cu = 0,
  279. LEGACY_In1_Cu,
  280. LEGACY_In2_Cu,
  281. LEGACY_In3_Cu,
  282. LEGACY_In4_Cu,
  283. LEGACY_In5_Cu,
  284. LEGACY_In6_Cu,
  285. LEGACY_In7_Cu,
  286. LEGACY_In8_Cu,
  287. LEGACY_In9_Cu,
  288. LEGACY_In10_Cu,
  289. LEGACY_In11_Cu,
  290. LEGACY_In12_Cu,
  291. LEGACY_In13_Cu,
  292. LEGACY_In14_Cu,
  293. LEGACY_In15_Cu,
  294. LEGACY_In16_Cu,
  295. LEGACY_In17_Cu,
  296. LEGACY_In18_Cu,
  297. LEGACY_In19_Cu,
  298. LEGACY_In20_Cu,
  299. LEGACY_In21_Cu,
  300. LEGACY_In22_Cu,
  301. LEGACY_In23_Cu,
  302. LEGACY_In24_Cu,
  303. LEGACY_In25_Cu,
  304. LEGACY_In26_Cu,
  305. LEGACY_In27_Cu,
  306. LEGACY_In28_Cu,
  307. LEGACY_In29_Cu,
  308. LEGACY_In30_Cu,
  309. LEGACY_B_Cu, // 31
  310. LEGACY_B_Adhes,
  311. LEGACY_F_Adhes,
  312. LEGACY_B_Paste,
  313. LEGACY_F_Paste,
  314. LEGACY_B_SilkS,
  315. LEGACY_F_SilkS,
  316. LEGACY_B_Mask,
  317. LEGACY_F_Mask, // 39
  318. LEGACY_Dwgs_User,
  319. LEGACY_Cmts_User,
  320. LEGACY_Eco1_User,
  321. LEGACY_Eco2_User,
  322. LEGACY_Edge_Cuts,
  323. LEGACY_Margin, // 45
  324. LEGACY_B_CrtYd,
  325. LEGACY_F_CrtYd,
  326. LEGACY_B_Fab,
  327. LEGACY_F_Fab, // 49
  328. // User definable layers.
  329. LEGACY_User_1,
  330. LEGACY_User_2,
  331. LEGACY_User_3,
  332. LEGACY_User_4,
  333. LEGACY_User_5,
  334. LEGACY_User_6,
  335. LEGACY_User_7,
  336. LEGACY_User_8,
  337. LEGACY_User_9,
  338. LEGACY_Rescue, // 59
  339. // Four reserved layers (60 - 63) for future expansion within the 64 bit integer limit.
  340. LEGACY_PCB_LAYER_ID_COUNT
  341. };
  342. /*
  343. * Mapping to translate a legacy layer ID into the new PCB layer IDs.
  344. */
  345. static const std::map<LEGACY_PCB_LAYER_ID, PCB_LAYER_ID> s_legacyLayerIdMap{
  346. {LEGACY_F_Cu, F_Cu},
  347. {LEGACY_B_Cu, B_Cu},
  348. {LEGACY_In1_Cu, In1_Cu},
  349. {LEGACY_In2_Cu, In2_Cu},
  350. {LEGACY_In3_Cu, In3_Cu},
  351. {LEGACY_In4_Cu, In4_Cu},
  352. {LEGACY_In5_Cu, In5_Cu},
  353. {LEGACY_In6_Cu, In6_Cu},
  354. {LEGACY_In7_Cu, In7_Cu},
  355. {LEGACY_In8_Cu, In8_Cu},
  356. {LEGACY_In9_Cu, In9_Cu},
  357. {LEGACY_In10_Cu, In10_Cu},
  358. {LEGACY_In11_Cu, In11_Cu},
  359. {LEGACY_In12_Cu, In12_Cu},
  360. {LEGACY_In13_Cu, In13_Cu},
  361. {LEGACY_In14_Cu, In14_Cu},
  362. {LEGACY_In15_Cu, In15_Cu},
  363. {LEGACY_In16_Cu, In16_Cu},
  364. {LEGACY_In17_Cu, In17_Cu},
  365. {LEGACY_In18_Cu, In18_Cu},
  366. {LEGACY_In19_Cu, In19_Cu},
  367. {LEGACY_In20_Cu, In20_Cu},
  368. {LEGACY_In21_Cu, In21_Cu},
  369. {LEGACY_In22_Cu, In22_Cu},
  370. {LEGACY_In23_Cu, In23_Cu},
  371. {LEGACY_In24_Cu, In24_Cu},
  372. {LEGACY_In25_Cu, In25_Cu},
  373. {LEGACY_In26_Cu, In26_Cu},
  374. {LEGACY_In27_Cu, In27_Cu},
  375. {LEGACY_In28_Cu, In28_Cu},
  376. {LEGACY_In29_Cu, In29_Cu},
  377. {LEGACY_In30_Cu, In30_Cu},
  378. {LEGACY_F_Mask, F_Mask},
  379. {LEGACY_B_Mask, B_Mask},
  380. {LEGACY_F_SilkS, F_SilkS},
  381. {LEGACY_B_SilkS, B_SilkS},
  382. {LEGACY_F_Adhes, F_Adhes},
  383. {LEGACY_B_Adhes, B_Adhes},
  384. {LEGACY_F_Paste, F_Paste},
  385. {LEGACY_B_Paste, B_Paste},
  386. {LEGACY_Dwgs_User, Dwgs_User},
  387. {LEGACY_Cmts_User, Cmts_User},
  388. {LEGACY_Eco1_User, Eco1_User},
  389. {LEGACY_Eco2_User, Eco2_User},
  390. {LEGACY_Edge_Cuts, Edge_Cuts},
  391. {LEGACY_Margin, Margin},
  392. {LEGACY_B_CrtYd, B_CrtYd},
  393. {LEGACY_F_CrtYd, F_CrtYd},
  394. {LEGACY_B_Fab, B_Fab},
  395. {LEGACY_F_Fab, F_Fab},
  396. {LEGACY_User_1, User_1},
  397. {LEGACY_User_2, User_2},
  398. {LEGACY_User_3, User_3},
  399. {LEGACY_User_4, User_4},
  400. {LEGACY_User_5, User_5},
  401. {LEGACY_User_6, User_6},
  402. {LEGACY_User_7, User_7},
  403. {LEGACY_User_8, User_8},
  404. {LEGACY_User_9, User_9},
  405. {LEGACY_Rescue, Rescue},
  406. };
  407. LSET remapLegacyLayerLSET( const BASE_SET& aLegacyLSET )
  408. {
  409. LSET newLayers;
  410. for( const auto& [legacyLayer, newLayer] : s_legacyLayerIdMap )
  411. newLayers[newLayer] = aLegacyLSET[legacyLayer];
  412. return newLayers;
  413. }
  414. void PCB_PLOT_PARAMS_PARSER::Parse( PCB_PLOT_PARAMS* aPcbPlotParams )
  415. {
  416. T token;
  417. while( ( token = NextTok() ) != T_RIGHT )
  418. {
  419. if( token == T_EOF)
  420. Unexpected( T_EOF );
  421. if( token == T_LEFT )
  422. token = NextTok();
  423. if( token == T_pcbplotparams )
  424. continue;
  425. bool skip_right = false;
  426. switch( token )
  427. {
  428. case T_layerselection:
  429. {
  430. token = NeedSYMBOLorNUMBER();
  431. const std::string& cur = CurStr();
  432. if( token == T_NUMBER ) // pretty 3 format had legacy Cu stack.
  433. {
  434. // It's not possible to convert a legacy Cu layer number to a new Cu layer
  435. // number without knowing the number or total Cu layers in the legacy board.
  436. // We do not have that information here, so simply set all layers ON. User
  437. // can turn them off in the UI.
  438. aPcbPlotParams->m_layerSelection = LSET( { F_SilkS, B_SilkS } ) | LSET::AllCuMask();
  439. }
  440. else if( cur.find_first_of( "0x" ) == 0 ) // pretty ver. 4.
  441. {
  442. // The layers were renumbered in 5e0abadb23425765e164f49ee2f893e94ddb97fc, but there wasn't
  443. // a board file version change with it, so this value is the one immediately after that happened.
  444. if( m_boardFileVersion < 20240819 )
  445. {
  446. BASE_SET legacyLSET( LEGACY_PCB_LAYER_ID_COUNT );
  447. // skip the leading 2 0x bytes.
  448. legacyLSET.ParseHex( cur.c_str() + 2, cur.size() - 2 );
  449. aPcbPlotParams->SetLayerSelection( remapLegacyLayerLSET( legacyLSET ) );
  450. }
  451. else
  452. {
  453. // skip the leading 2 0x bytes.
  454. aPcbPlotParams->m_layerSelection.ParseHex( cur.c_str() + 2, cur.size() - 2 );
  455. }
  456. }
  457. else
  458. {
  459. Expecting( "integer or hex layerSelection" );
  460. }
  461. break;
  462. }
  463. case T_plot_on_all_layers_selection:
  464. {
  465. token = NeedSYMBOLorNUMBER();
  466. const std::string& cur = CurStr();
  467. if( cur.find_first_of( "0x" ) == 0 )
  468. {
  469. LSET layers;
  470. // The layers were renumbered in 5e0abadb23425765e164f49ee2f893e94ddb97fc, but
  471. // there wasn't a board file version change with it, so this value is the one
  472. // immediately after that happened.
  473. if( m_boardFileVersion < 20240819 )
  474. {
  475. BASE_SET legacyLSET( LEGACY_PCB_LAYER_ID_COUNT );
  476. // skip the leading 2 0x bytes.
  477. legacyLSET.ParseHex( cur.c_str() + 2, cur.size() - 2 );
  478. layers = remapLegacyLayerLSET( legacyLSET );
  479. }
  480. else
  481. {
  482. // skip the leading 2 0x bytes.
  483. layers.ParseHex( cur.c_str() + 2, cur.size() - 2 );
  484. }
  485. aPcbPlotParams->SetPlotOnAllLayersSequence( layers.SeqStackupForPlotting() );
  486. }
  487. else
  488. {
  489. Expecting( "hex plot_on_all_layers_selection" );
  490. }
  491. break;
  492. }
  493. case T_disableapertmacros:
  494. aPcbPlotParams->m_gerberDisableApertMacros = parseBool();
  495. break;
  496. case T_usegerberextensions:
  497. aPcbPlotParams->m_useGerberProtelExtensions = parseBool();
  498. break;
  499. case T_usegerberattributes:
  500. aPcbPlotParams->m_useGerberX2format = parseBool();
  501. break;
  502. case T_usegerberadvancedattributes:
  503. aPcbPlotParams->m_includeGerberNetlistInfo = parseBool();
  504. break;
  505. case T_creategerberjobfile:
  506. aPcbPlotParams->m_createGerberJobFile = parseBool();
  507. break;
  508. case T_gerberprecision:
  509. aPcbPlotParams->m_gerberPrecision = parseInt( gbrDefaultPrecision - 1,
  510. gbrDefaultPrecision);
  511. break;
  512. case T_dashed_line_dash_ratio:
  513. aPcbPlotParams->m_dashedLineDashRatio = parseDouble();
  514. break;
  515. case T_dashed_line_gap_ratio:
  516. aPcbPlotParams->m_dashedLineGapRatio = parseDouble();
  517. break;
  518. case T_svgprecision:
  519. aPcbPlotParams->m_svgPrecision = parseInt( SVG_PRECISION_MIN, SVG_PRECISION_MAX );
  520. break;
  521. case T_svguseinch:
  522. parseBool(); // Unused. For compatibility
  523. break;
  524. case T_psa4output:
  525. aPcbPlotParams->m_A4Output = parseBool();
  526. break;
  527. case T_excludeedgelayer:
  528. if( !parseBool() )
  529. aPcbPlotParams->m_plotOnAllLayersSequence.push_back( Edge_Cuts );
  530. break;
  531. case T_plotframeref:
  532. aPcbPlotParams->m_plotDrawingSheet = parseBool();
  533. break;
  534. case T_viasonmask:
  535. aPcbPlotParams->m_plotViaOnMaskLayer = parseBool();
  536. break;
  537. case T_useauxorigin:
  538. aPcbPlotParams->m_useAuxOrigin = parseBool();
  539. break;
  540. case T_mode:
  541. case T_hpglpennumber:
  542. case T_hpglpenspeed:
  543. case T_hpglpenoverlay:
  544. // HPGL is no longer supported
  545. parseInt( std::numeric_limits<int>::min(), std::numeric_limits<int>::max() );
  546. break;
  547. case T_pdf_front_fp_property_popups:
  548. aPcbPlotParams->m_PDFFrontFPPropertyPopups = parseBool();
  549. break;
  550. case T_pdf_back_fp_property_popups:
  551. aPcbPlotParams->m_PDFBackFPPropertyPopups = parseBool();
  552. break;
  553. case T_pdf_metadata:
  554. aPcbPlotParams->m_PDFMetadata = parseBool();
  555. break;
  556. case T_pdf_single_document:
  557. aPcbPlotParams->m_PDFSingle = parseBool();
  558. break;
  559. case T_dxfpolygonmode:
  560. aPcbPlotParams->m_DXFPolygonMode = parseBool();
  561. break;
  562. case T_dxfimperialunits:
  563. aPcbPlotParams->m_DXFUnits = parseBool() ? DXF_UNITS::INCH : DXF_UNITS::MM;
  564. break;
  565. case T_dxfusepcbnewfont:
  566. aPcbPlotParams->m_textMode = parseBool() ? PLOT_TEXT_MODE::DEFAULT
  567. : PLOT_TEXT_MODE::NATIVE;
  568. break;
  569. case T_pscolor:
  570. NeedSYMBOL(); // This actually was never used...
  571. break;
  572. case T_psnegative:
  573. aPcbPlotParams->m_negative = parseBool();
  574. break;
  575. case T_plot_black_and_white:
  576. aPcbPlotParams->m_blackAndWhite = parseBool();
  577. break;
  578. case T_plotinvisibletext: // legacy token; no longer supported
  579. parseBool();
  580. break;
  581. case T_sketchpadsonfab:
  582. aPcbPlotParams->m_sketchPadsOnFabLayers= parseBool();
  583. break;
  584. case T_plotpadnumbers:
  585. aPcbPlotParams->m_plotPadNumbers = parseBool();
  586. break;
  587. case T_hidednponfab:
  588. aPcbPlotParams->m_hideDNPFPsOnFabLayers = parseBool();
  589. break;
  590. case T_sketchdnponfab:
  591. aPcbPlotParams->m_sketchDNPFPsOnFabLayers = parseBool();
  592. break;
  593. case T_crossoutdnponfab:
  594. aPcbPlotParams->m_crossoutDNPFPsOnFabLayers = parseBool();
  595. break;
  596. case T_subtractmaskfromsilk:
  597. aPcbPlotParams->m_subtractMaskFromSilk = parseBool();
  598. break;
  599. case T_outputformat:
  600. aPcbPlotParams->m_format = static_cast<PLOT_FORMAT>(
  601. parseInt( static_cast<int>( PLOT_FORMAT::FIRST_FORMAT ),
  602. static_cast<int>( PLOT_FORMAT::LAST_FORMAT ) ) );
  603. break;
  604. case T_mirror:
  605. aPcbPlotParams->m_mirror = parseBool();
  606. break;
  607. case T_drillshape:
  608. aPcbPlotParams->m_drillMarks = static_cast<DRILL_MARKS> ( parseInt( 0, 2 ) );
  609. break;
  610. case T_scaleselection:
  611. aPcbPlotParams->m_scaleSelection = parseInt( 0, 4 );
  612. break;
  613. case T_outputdirectory:
  614. NeedSYMBOLorNUMBER(); // a dir name can be like a number
  615. aPcbPlotParams->m_outputDirectory = From_UTF8( CurText() );
  616. break;
  617. default:
  618. skipCurrent(); // skip unknown or outdated plot parameter
  619. skip_right = true; // the closing right token is already read.
  620. break;
  621. }
  622. if( ! skip_right )
  623. NeedRIGHT();
  624. }
  625. }
  626. bool PCB_PLOT_PARAMS_PARSER::parseBool()
  627. {
  628. T token = NeedSYMBOL();
  629. switch( token )
  630. {
  631. case T_false:
  632. case T_no:
  633. return false;
  634. case T_true:
  635. case T_yes:
  636. return true;
  637. default:
  638. Expecting( "true, false, yes, or no" );
  639. return false;
  640. }
  641. }
  642. int PCB_PLOT_PARAMS_PARSER::parseInt( int aMin, int aMax )
  643. {
  644. T token = NextTok();
  645. if( token != T_NUMBER )
  646. Expecting( T_NUMBER );
  647. int val = atoi( CurText() );
  648. if( val < aMin )
  649. val = aMin;
  650. else if( val > aMax )
  651. val = aMax;
  652. return val;
  653. }
  654. double PCB_PLOT_PARAMS_PARSER::parseDouble()
  655. {
  656. T token = NextTok();
  657. if( token != T_NUMBER )
  658. Expecting( T_NUMBER );
  659. return DSNLEXER::parseDouble();
  660. }
  661. void PCB_PLOT_PARAMS_PARSER::skipCurrent()
  662. {
  663. int curr_level = 0;
  664. T token;
  665. while( ( token = NextTok() ) != T_EOF )
  666. {
  667. if( token == T_LEFT )
  668. curr_level--;
  669. if( token == T_RIGHT )
  670. {
  671. curr_level++;
  672. if( curr_level > 0 )
  673. return;
  674. }
  675. }
  676. }