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.

1059 lines
41 KiB

8 years ago
14 years ago
6 years ago
14 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 1992-2019 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 <dimension.h>
  24. #include <track.h>
  25. #include <layers_id_colors_and_visibility.h>
  26. #include <kiface_i.h>
  27. #include <board_design_settings.h>
  28. #include <drc/drc_item.h>
  29. #include <drc/drc_engine.h>
  30. #include <settings/parameters.h>
  31. #include <project/project_file.h>
  32. #include <advanced_config.h>
  33. const int bdsSchemaVersion = 1;
  34. BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
  35. NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aParent, aPath ),
  36. m_Pad_Master( NULL )
  37. {
  38. // We want to leave alone parameters that aren't found in the project JSON as they may be
  39. // initialized by the board file parser before NESTED_SETTINGS::LoadFromFile is called.
  40. m_resetParamsIfMissing = false;
  41. // Create a default NETCLASS list so that things don't break horribly if there's no project
  42. // loaded. This also is used during file load for legacy boards that have netclasses stored
  43. // in the file. After load, this information will be moved to the project and the pointer
  44. // updated.
  45. m_netClasses = &m_internalNetClasses;
  46. m_HasStackup = false; // no stackup defined by default
  47. LSET all_set = LSET().set();
  48. m_enabledLayers = all_set; // All layers enabled at first.
  49. // SetCopperLayerCount() will adjust this.
  50. SetCopperLayerCount( 2 ); // Default design is a double sided board
  51. m_CurrentViaType = VIATYPE::THROUGH;
  52. // if true, when creating a new track starting on an existing track, use this track width
  53. m_UseConnectedTrackWidth = false;
  54. m_BlindBuriedViaAllowed = false;
  55. m_MicroViasAllowed = false;
  56. // First is always the reference designator
  57. m_DefaultFPTextItems.emplace_back( wxT( "REF**" ), true, F_SilkS );
  58. // Second is always the value
  59. m_DefaultFPTextItems.emplace_back( wxT( "" ), true, F_Fab );
  60. // Any following ones are freebies
  61. m_DefaultFPTextItems.emplace_back( wxT( "${REF}" ), true, F_Fab );
  62. m_LineThickness[ LAYER_CLASS_SILK ] = Millimeter2iu( DEFAULT_SILK_LINE_WIDTH );
  63. m_TextSize[ LAYER_CLASS_SILK ] = wxSize( Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ),
  64. Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ) );
  65. m_TextThickness[ LAYER_CLASS_SILK ] = Millimeter2iu( DEFAULT_SILK_TEXT_WIDTH );
  66. m_TextItalic[ LAYER_CLASS_SILK ] = false;
  67. m_TextUpright[ LAYER_CLASS_SILK ] = false;
  68. m_LineThickness[ LAYER_CLASS_COPPER ] = Millimeter2iu( DEFAULT_COPPER_LINE_WIDTH );
  69. m_TextSize[ LAYER_CLASS_COPPER ] = wxSize( Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ),
  70. Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ) );
  71. m_TextThickness[ LAYER_CLASS_COPPER ] = Millimeter2iu( DEFAULT_COPPER_TEXT_WIDTH );
  72. m_TextItalic[ LAYER_CLASS_COPPER ] = false;
  73. m_TextUpright[ LAYER_CLASS_COPPER ] = false;
  74. // Edges & Courtyards; text properties aren't used but better to have them holding
  75. // reasonable values than not.
  76. m_LineThickness[ LAYER_CLASS_EDGES ] = Millimeter2iu( DEFAULT_EDGE_WIDTH );
  77. m_TextSize[ LAYER_CLASS_EDGES ] = wxSize( Millimeter2iu( DEFAULT_TEXT_SIZE ),
  78. Millimeter2iu( DEFAULT_TEXT_SIZE ) );
  79. m_TextThickness[ LAYER_CLASS_EDGES ] = Millimeter2iu( DEFAULT_TEXT_WIDTH );
  80. m_TextItalic[ LAYER_CLASS_EDGES ] = false;
  81. m_TextUpright[ LAYER_CLASS_EDGES ] = false;
  82. m_LineThickness[ LAYER_CLASS_COURTYARD ] = Millimeter2iu( DEFAULT_COURTYARD_WIDTH );
  83. m_TextSize[ LAYER_CLASS_COURTYARD ] = wxSize( Millimeter2iu( DEFAULT_TEXT_SIZE ),
  84. Millimeter2iu( DEFAULT_TEXT_SIZE ) );
  85. m_TextThickness[ LAYER_CLASS_COURTYARD ] = Millimeter2iu( DEFAULT_TEXT_WIDTH );
  86. m_TextItalic[ LAYER_CLASS_COURTYARD ] = false;
  87. m_TextUpright[ LAYER_CLASS_COURTYARD ] = false;
  88. m_LineThickness[ LAYER_CLASS_FAB ] = Millimeter2iu( DEFAULT_LINE_WIDTH );
  89. m_TextSize[ LAYER_CLASS_FAB ] = wxSize( Millimeter2iu( DEFAULT_TEXT_SIZE ),
  90. Millimeter2iu( DEFAULT_TEXT_SIZE ) );
  91. m_TextThickness[ LAYER_CLASS_FAB ] = Millimeter2iu( DEFAULT_TEXT_WIDTH );
  92. m_TextItalic[ LAYER_CLASS_FAB ] = false;
  93. m_TextUpright[ LAYER_CLASS_FAB ] = false;
  94. m_LineThickness[ LAYER_CLASS_OTHERS ] = Millimeter2iu( DEFAULT_LINE_WIDTH );
  95. m_TextSize[ LAYER_CLASS_OTHERS ] = wxSize( Millimeter2iu( DEFAULT_TEXT_SIZE ),
  96. Millimeter2iu( DEFAULT_TEXT_SIZE ) );
  97. m_TextThickness[ LAYER_CLASS_OTHERS ] = Millimeter2iu( DEFAULT_TEXT_WIDTH );
  98. m_TextItalic[ LAYER_CLASS_OTHERS ] = false;
  99. m_TextUpright[ LAYER_CLASS_OTHERS ] = false;
  100. m_DimensionPrecision = 4;
  101. m_DimensionUnitsMode = DIM_UNITS_MODE::AUTOMATIC;
  102. m_DimensionUnitsFormat = DIM_UNITS_FORMAT::BARE_SUFFIX;
  103. m_DimensionSuppressZeroes = false;
  104. m_DimensionTextPosition = DIM_TEXT_POSITION::OUTSIDE;
  105. m_DimensionKeepTextAligned = true;
  106. m_DimensionArrowLength = Mils2iu( DEFAULT_DIMENSION_ARROW_LENGTH );
  107. m_DimensionExtensionOffset = Millimeter2iu( DEFAULT_DIMENSION_EXTENSION_OFFSET );
  108. m_useCustomTrackVia = false;
  109. m_customTrackWidth = Millimeter2iu( DEFAULT_CUSTOMTRACKWIDTH );
  110. m_customViaSize.m_Diameter = Millimeter2iu( DEFAULT_VIASMINSIZE );
  111. m_customViaSize.m_Drill = Millimeter2iu( DEFAULT_MINTHROUGHDRILL );
  112. m_useCustomDiffPair = false;
  113. m_customDiffPair.m_Width = Millimeter2iu( DEFAULT_CUSTOMDPAIRWIDTH );
  114. m_customDiffPair.m_Gap = Millimeter2iu( DEFAULT_CUSTOMDPAIRGAP );
  115. m_customDiffPair.m_ViaGap = Millimeter2iu( DEFAULT_CUSTOMDPAIRVIAGAP );
  116. m_MinClearance = Millimeter2iu( DEFAULT_MINCLEARANCE );
  117. m_TrackMinWidth = Millimeter2iu( DEFAULT_TRACKMINWIDTH );
  118. m_ViasMinAnnulus = Millimeter2iu( DEFAULT_VIASMINSIZE - DEFAULT_MINTHROUGHDRILL ) / 2;
  119. m_ViasMinSize = Millimeter2iu( DEFAULT_VIASMINSIZE );
  120. m_MinThroughDrill = Millimeter2iu( DEFAULT_MINTHROUGHDRILL );
  121. m_MicroViasMinSize = Millimeter2iu( DEFAULT_MICROVIASMINSIZE );
  122. m_MicroViasMinDrill = Millimeter2iu( DEFAULT_MICROVIASMINDRILL );
  123. m_CopperEdgeClearance = Millimeter2iu( DEFAULT_COPPEREDGECLEARANCE );
  124. m_HoleClearance = Millimeter2iu( DEFAULT_HOLECLEARANCE );
  125. m_HoleToHoleMin = Millimeter2iu( DEFAULT_HOLETOHOLEMIN );
  126. m_SilkClearance = Millimeter2iu( DEFAULT_SILKCLEARANCE );
  127. for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode )
  128. m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
  129. m_DRCSeverities[ DRCE_MISSING_COURTYARD ] = RPT_SEVERITY_IGNORE;
  130. m_DRCSeverities[ DRCE_PTH_IN_COURTYARD ] = RPT_SEVERITY_IGNORE;
  131. m_DRCSeverities[ DRCE_NPTH_IN_COURTYARD ] = RPT_SEVERITY_IGNORE;
  132. m_DRCSeverities[ DRCE_DANGLING_TRACK ] = RPT_SEVERITY_WARNING;
  133. m_DRCSeverities[ DRCE_DANGLING_VIA ] = RPT_SEVERITY_WARNING;
  134. m_DRCSeverities[ DRCE_MISSING_FOOTPRINT ] = RPT_SEVERITY_WARNING;
  135. m_DRCSeverities[ DRCE_DUPLICATE_FOOTPRINT ] = RPT_SEVERITY_WARNING;
  136. m_DRCSeverities[ DRCE_EXTRA_FOOTPRINT ] = RPT_SEVERITY_WARNING;
  137. m_DRCSeverities[ DRCE_NET_CONFLICT ] = RPT_SEVERITY_WARNING;
  138. m_MaxError = ARC_HIGH_DEF;
  139. m_ZoneFillVersion = 6; // Use new algo by default to fill zones
  140. m_ZoneKeepExternalFillets = false; // Use new algo by default. Legacy boards might
  141. // want to set it to true for old algo....
  142. // Global mask margins:
  143. m_SolderMaskMargin = Millimeter2iu( DEFAULT_SOLDERMASK_CLEARANCE );
  144. m_SolderMaskMinWidth = Millimeter2iu( DEFAULT_SOLDERMASK_MIN_WIDTH );
  145. m_SolderPasteMargin = 0; // Solder paste margin absolute value
  146. m_SolderPasteMarginRatio = 0.0; // Solder paste margin as a ratio of pad size
  147. // The final margin is the sum of these 2 values
  148. // Usually < 0 because the mask is smaller than pad
  149. // Layer thickness for 3D viewer
  150. m_boardThickness = Millimeter2iu( DEFAULT_BOARD_THICKNESS_MM );
  151. m_viaSizeIndex = 0;
  152. m_trackWidthIndex = 0;
  153. m_diffPairIndex = 0;
  154. // Parameters stored in JSON in the project file
  155. // NOTE: Previously, BOARD_DESIGN_SETTINGS stored the basic board layer information (layer
  156. // names and enable/disable state) in the project file even though this information is also
  157. // stored in the board file. This was implemented for importing these settings from another
  158. // project. Going forward, the import feature will just import from other board files (since
  159. // we could have multi-board projects in the future anyway) so this functionality is dropped.
  160. m_params.emplace_back( new PARAM<bool>( "rules.allow_microvias", &m_MicroViasAllowed, false ) );
  161. m_params.emplace_back( new PARAM<bool>( "rules.allow_blind_buried_vias",
  162. &m_BlindBuriedViaAllowed, false ) );
  163. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_clearance", &m_MinClearance,
  164. Millimeter2iu( DEFAULT_MINCLEARANCE ), Millimeter2iu( 0.01 ), Millimeter2iu( 25.0 ),
  165. MM_PER_IU ) );
  166. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_track_width", &m_TrackMinWidth,
  167. Millimeter2iu( DEFAULT_TRACKMINWIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 25.0 ),
  168. MM_PER_IU ) );
  169. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_annular_width", &m_ViasMinAnnulus,
  170. Millimeter2iu( DEFAULT_VIASMINSIZE ), Millimeter2iu( 0.01 ), Millimeter2iu( 25.0 ),
  171. MM_PER_IU ) );
  172. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_diameter", &m_ViasMinSize,
  173. Millimeter2iu( DEFAULT_VIASMINSIZE ), Millimeter2iu( 0.01 ), Millimeter2iu( 25.0 ),
  174. MM_PER_IU ) );
  175. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_through_hole_diameter",
  176. &m_MinThroughDrill, Millimeter2iu( DEFAULT_MINTHROUGHDRILL ), Millimeter2iu( 0.01 ),
  177. Millimeter2iu( 25.0 ), MM_PER_IU ) );
  178. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_diameter",
  179. &m_MicroViasMinSize, Millimeter2iu( DEFAULT_MICROVIASMINSIZE ), Millimeter2iu( 0.01 ),
  180. Millimeter2iu( 10.0 ), MM_PER_IU ) );
  181. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_drill", &m_MicroViasMinDrill,
  182. Millimeter2iu( DEFAULT_MICROVIASMINDRILL ), Millimeter2iu( 0.01 ),
  183. Millimeter2iu( 10.0 ), MM_PER_IU ) );
  184. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_to_hole", &m_HoleToHoleMin,
  185. Millimeter2iu( DEFAULT_HOLETOHOLEMIN ), Millimeter2iu( 0.00 ), Millimeter2iu( 10.0 ),
  186. MM_PER_IU ) );
  187. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_clearance", &m_HoleClearance,
  188. Millimeter2iu( DEFAULT_HOLECLEARANCE ), Millimeter2iu( 0.00 ), Millimeter2iu( 100.0 ),
  189. MM_PER_IU ) );
  190. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_silk_clearance", &m_SilkClearance,
  191. Millimeter2iu( DEFAULT_SILKCLEARANCE ), Millimeter2iu( 0.00 ), Millimeter2iu( 100.0 ),
  192. MM_PER_IU ) );
  193. // Note: a clearance of -0.01 is a flag indicating we should use the legacy (pre-6.0) method
  194. // based on the edge cut thicknesses.
  195. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_copper_edge_clearance",
  196. &m_CopperEdgeClearance, Millimeter2iu( LEGACY_COPPEREDGECLEARANCE ),
  197. Millimeter2iu( -0.01 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
  198. m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_mask_clearance",
  199. &m_SolderMaskMargin, Millimeter2iu( DEFAULT_SOLDERMASK_CLEARANCE ),
  200. Millimeter2iu( -1.0 ), Millimeter2iu( 1.0 ), MM_PER_IU ) );
  201. m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_mask_min_width",
  202. &m_SolderMaskMinWidth, Millimeter2iu( DEFAULT_SOLDERMASK_MIN_WIDTH ), 0,
  203. Millimeter2iu( 1.0 ), MM_PER_IU ) );
  204. m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_paste_clearance",
  205. &m_SolderPasteMargin, Millimeter2iu( DEFAULT_SOLDERPASTE_CLEARANCE ),
  206. Millimeter2iu( -1.0 ), Millimeter2iu( 1.0 ), MM_PER_IU ) );
  207. m_params.emplace_back( new PARAM<double>( "rules.solder_paste_margin_ratio",
  208. &m_SolderPasteMarginRatio, DEFAULT_SOLDERPASTE_RATIO, -0.5, 1.0 ) );
  209. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
  210. [&]() -> nlohmann::json
  211. {
  212. nlohmann::json ret = {};
  213. for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
  214. {
  215. wxString name = item.GetSettingsKey();
  216. int code = item.GetErrorCode();
  217. if( name.IsEmpty() || m_DRCSeverities.count( code ) == 0 )
  218. continue;
  219. ret[std::string( name.ToUTF8() )] = SeverityToString( m_DRCSeverities[code] );
  220. }
  221. return ret;
  222. },
  223. [&]( const nlohmann::json& aJson )
  224. {
  225. if( !aJson.is_object() )
  226. return;
  227. for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
  228. {
  229. wxString name = item.GetSettingsKey();
  230. std::string key( name.ToUTF8() );
  231. if( aJson.contains( key ) )
  232. m_DRCSeverities[item.GetErrorCode()] = SeverityFromString( aJson[key] );
  233. }
  234. }, {} ) );
  235. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "drc_exclusions",
  236. [&]() -> nlohmann::json
  237. {
  238. nlohmann::json js = nlohmann::json::array();
  239. for( const auto& entry : m_DrcExclusions )
  240. js.push_back( entry );
  241. return js;
  242. },
  243. [&]( const nlohmann::json& aObj )
  244. {
  245. m_DrcExclusions.clear();
  246. if( !aObj.is_array() )
  247. return;
  248. for( const nlohmann::json& entry : aObj )
  249. {
  250. if( entry.empty() )
  251. continue;
  252. m_DrcExclusions.insert( entry.get<wxString>() );
  253. }
  254. },
  255. {} ) );
  256. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "track_widths",
  257. [&]() -> nlohmann::json
  258. {
  259. nlohmann::json js = nlohmann::json::array();
  260. for( const int& width : m_TrackWidthList )
  261. js.push_back( Iu2Millimeter( width ) );
  262. return js;
  263. },
  264. [&]( const nlohmann::json& aJson )
  265. {
  266. if( !aJson.is_array() )
  267. return;
  268. m_TrackWidthList.clear();
  269. for( const nlohmann::json& entry : aJson )
  270. {
  271. if( entry.empty() )
  272. continue;
  273. m_TrackWidthList.emplace_back( Millimeter2iu( entry.get<double>() ) );
  274. }
  275. },
  276. {} ) );
  277. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "via_dimensions",
  278. [&]() -> nlohmann::json
  279. {
  280. nlohmann::json js = nlohmann::json::array();
  281. for( const auto& via : m_ViasDimensionsList )
  282. {
  283. nlohmann::json entry = {};
  284. entry["diameter"] = Iu2Millimeter( via.m_Diameter );
  285. entry["drill"] = Iu2Millimeter( via.m_Drill );
  286. js.push_back( entry );
  287. }
  288. return js;
  289. },
  290. [&]( const nlohmann::json& aObj )
  291. {
  292. if( !aObj.is_array() )
  293. return;
  294. m_ViasDimensionsList.clear();
  295. for( const nlohmann::json& entry : aObj )
  296. {
  297. if( entry.empty() || !entry.is_object() )
  298. continue;
  299. if( !entry.contains( "diameter" ) || !entry.contains( "drill" ) )
  300. continue;
  301. int diameter = Millimeter2iu( entry["diameter"].get<double>() );
  302. int drill = Millimeter2iu( entry["drill"].get<double>() );
  303. m_ViasDimensionsList.emplace_back( VIA_DIMENSION( diameter, drill ) );
  304. }
  305. },
  306. {} ) );
  307. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "diff_pair_dimensions",
  308. [&]() -> nlohmann::json
  309. {
  310. nlohmann::json js = nlohmann::json::array();
  311. for( const auto& pair : m_DiffPairDimensionsList )
  312. {
  313. nlohmann::json entry = {};
  314. entry["width"] = Iu2Millimeter( pair.m_Width );
  315. entry["gap"] = Iu2Millimeter( pair.m_Gap );
  316. entry["via_gap"] = Iu2Millimeter( pair.m_ViaGap );
  317. js.push_back( entry );
  318. }
  319. return js;
  320. },
  321. [&]( const nlohmann::json& aObj )
  322. {
  323. if( !aObj.is_array() )
  324. return;
  325. m_DiffPairDimensionsList.clear();
  326. for( const nlohmann::json& entry : aObj )
  327. {
  328. if( entry.empty() || !entry.is_object() )
  329. continue;
  330. if( !entry.contains( "width" ) || !entry.contains( "gap" )
  331. || !entry.contains( "via_gap" ) )
  332. continue;
  333. int width = Millimeter2iu( entry["width"].get<double>() );
  334. int gap = Millimeter2iu( entry["gap"].get<double>() );
  335. int via_gap = Millimeter2iu( entry["via_gap"].get<double>() );
  336. m_DiffPairDimensionsList.emplace_back(
  337. DIFF_PAIR_DIMENSION( width, gap, via_gap ) );
  338. }
  339. },
  340. {} ) );
  341. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_line_width",
  342. &m_LineThickness[LAYER_CLASS_SILK], Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ),
  343. Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
  344. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_v",
  345. &m_TextSize[LAYER_CLASS_SILK].y, Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ),
  346. TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
  347. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_h",
  348. &m_TextSize[LAYER_CLASS_SILK].x, Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ),
  349. TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
  350. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_thickness",
  351. &m_TextThickness[LAYER_CLASS_SILK], Millimeter2iu( DEFAULT_SILK_TEXT_WIDTH ), 1,
  352. TEXTS_MAX_WIDTH, MM_PER_IU ) );
  353. m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_italic",
  354. &m_TextItalic[LAYER_CLASS_SILK], false ) );
  355. m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_upright",
  356. &m_TextUpright[ LAYER_CLASS_SILK ], true ) );
  357. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_line_width",
  358. &m_LineThickness[LAYER_CLASS_COPPER], Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ),
  359. Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
  360. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_v",
  361. &m_TextSize[LAYER_CLASS_COPPER].y, Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ),
  362. TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
  363. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_h",
  364. &m_TextSize[LAYER_CLASS_COPPER].x, Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ),
  365. TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
  366. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_thickness",
  367. &m_TextThickness[LAYER_CLASS_COPPER], Millimeter2iu( DEFAULT_COPPER_TEXT_WIDTH ),
  368. Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
  369. m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_italic",
  370. &m_TextItalic[LAYER_CLASS_COPPER], false ) );
  371. m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_upright",
  372. &m_TextUpright[LAYER_CLASS_COPPER], true ) );
  373. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.board_outline_line_width",
  374. &m_LineThickness[LAYER_CLASS_EDGES], Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ),
  375. Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
  376. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.courtyard_line_width",
  377. &m_LineThickness[LAYER_CLASS_COURTYARD], Millimeter2iu( DEFAULT_COURTYARD_WIDTH ),
  378. Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
  379. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_line_width",
  380. &m_LineThickness[LAYER_CLASS_FAB], Millimeter2iu( DEFAULT_LINE_WIDTH ),
  381. Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
  382. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_v",
  383. &m_TextSize[LAYER_CLASS_FAB].y, Millimeter2iu( DEFAULT_TEXT_SIZE ),
  384. TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
  385. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_h",
  386. &m_TextSize[LAYER_CLASS_FAB].x, Millimeter2iu( DEFAULT_TEXT_SIZE ),
  387. TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
  388. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_thickness",
  389. &m_TextThickness[LAYER_CLASS_FAB], Millimeter2iu( DEFAULT_TEXT_WIDTH ),
  390. Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
  391. m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_italic",
  392. &m_TextItalic[LAYER_CLASS_FAB], false ) );
  393. m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_upright",
  394. &m_TextUpright[LAYER_CLASS_FAB], true ) );
  395. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_line_width",
  396. &m_LineThickness[LAYER_CLASS_OTHERS], Millimeter2iu( DEFAULT_LINE_WIDTH ),
  397. Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
  398. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_v",
  399. &m_TextSize[LAYER_CLASS_OTHERS].y, Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE,
  400. TEXTS_MAX_SIZE, MM_PER_IU ) );
  401. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_h",
  402. &m_TextSize[LAYER_CLASS_OTHERS].x, Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE,
  403. TEXTS_MAX_SIZE, MM_PER_IU ) );
  404. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_thickness",
  405. &m_TextThickness[LAYER_CLASS_OTHERS], Millimeter2iu( DEFAULT_TEXT_WIDTH ),
  406. Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
  407. m_params.emplace_back( new PARAM<bool>( "defaults.other_text_italic",
  408. &m_TextItalic[LAYER_CLASS_OTHERS], false ) );
  409. m_params.emplace_back( new PARAM<bool>( "defaults.other_text_upright",
  410. &m_TextUpright[LAYER_CLASS_OTHERS], true ) );
  411. m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_MODE>( "defaults.dimension_units",
  412. &m_DimensionUnitsMode, DIM_UNITS_MODE::AUTOMATIC, DIM_UNITS_MODE::INCHES,
  413. DIM_UNITS_MODE::AUTOMATIC ) );
  414. m_params.emplace_back( new PARAM<int>( "defaults.dimension_precision",
  415. &m_DimensionPrecision, 4, 0, 5 ) );
  416. m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_FORMAT>( "defaults.dimensions.units_format",
  417. &m_DimensionUnitsFormat, DIM_UNITS_FORMAT::BARE_SUFFIX, DIM_UNITS_FORMAT::NO_SUFFIX,
  418. DIM_UNITS_FORMAT::PAREN_SUFFIX ) );
  419. m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.suppress_zeroes",
  420. &m_DimensionSuppressZeroes, false ) );
  421. // NOTE: excluding DIM_TEXT_POSITION::MANUAL from the valid range here
  422. m_params.emplace_back( new PARAM_ENUM<DIM_TEXT_POSITION>( "defaults.dimensions.text_position",
  423. &m_DimensionTextPosition, DIM_TEXT_POSITION::OUTSIDE, DIM_TEXT_POSITION::OUTSIDE,
  424. DIM_TEXT_POSITION::INLINE ) );
  425. m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.keep_text_aligned",
  426. &m_DimensionKeepTextAligned, true ) );
  427. m_params.emplace_back( new PARAM<int>( "defaults.dimensions.arrow_length",
  428. &m_DimensionArrowLength,
  429. Mils2iu( DEFAULT_DIMENSION_ARROW_LENGTH ) ) );
  430. m_params.emplace_back( new PARAM<int>( "defaults.dimensions.extension_offset",
  431. &m_DimensionExtensionOffset,
  432. Millimeter2iu( DEFAULT_DIMENSION_EXTENSION_OFFSET ) ) );
  433. m_params.emplace_back( new PARAM<bool>( "defaults.zones.45_degree_only",
  434. &m_defaultZoneSettings.m_Zone_45_Only, false ) );
  435. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.zones.min_clearance",
  436. &m_defaultZoneSettings.m_ZoneClearance, Mils2iu( ZONE_CLEARANCE_MIL ),
  437. Millimeter2iu( 0.0 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
  438. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "defaults.pads",
  439. [&]() -> nlohmann::json
  440. {
  441. nlohmann::json ret =
  442. {
  443. { "width", Iu2Millimeter( m_Pad_Master.GetSize().x ) },
  444. { "height", Iu2Millimeter( m_Pad_Master.GetSize().y ) },
  445. { "drill", Iu2Millimeter( m_Pad_Master.GetDrillSize().x ) }
  446. };
  447. return ret;
  448. },
  449. [&]( const nlohmann::json& aJson )
  450. {
  451. if( aJson.contains( "width" ) && aJson.contains( "height" )
  452. && aJson.contains( "drill" ) )
  453. {
  454. wxSize sz;
  455. sz.SetWidth( Millimeter2iu( aJson["width"].get<double>() ) );
  456. sz.SetHeight( Millimeter2iu( aJson["height"].get<double>() ) );
  457. m_Pad_Master.SetSize( sz );
  458. int drill = Millimeter2iu( aJson["drill"].get<double>() );
  459. m_Pad_Master.SetDrillSize( wxSize( drill, drill ) );
  460. }
  461. }, {} ) );
  462. m_params.emplace_back( new PARAM_SCALED<int>( "rules.max_error", &m_MaxError, ARC_HIGH_DEF,
  463. Millimeter2iu( 0.0001 ), Millimeter2iu( 1.0 ), MM_PER_IU ) );
  464. // TODO: replace with zones_fill_version parameter and migrate zones_use_no_outline?
  465. m_params.emplace_back( new PARAM_LAMBDA<bool>( "zones_use_no_outline",
  466. [this]() -> bool
  467. {
  468. return m_ZoneFillVersion >= 6;
  469. },
  470. [this]( bool aVal )
  471. {
  472. m_ZoneFillVersion = aVal ? 6 : 5;
  473. },
  474. 6 ) );
  475. m_params.emplace_back( new PARAM<bool>( "zones_allow_external_fillets",
  476. &m_ZoneKeepExternalFillets, false ) );
  477. registerMigration( 0, 1, std::bind( &BOARD_DESIGN_SETTINGS::migrateSchema0to1, this ) );
  478. }
  479. BOARD_DESIGN_SETTINGS::~BOARD_DESIGN_SETTINGS()
  480. {
  481. if( m_parent )
  482. {
  483. m_parent->ReleaseNestedSettings( this );
  484. m_parent = nullptr;
  485. }
  486. }
  487. BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( const BOARD_DESIGN_SETTINGS& aOther ) :
  488. NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aOther.m_parent,
  489. aOther.m_path ),
  490. m_Pad_Master( nullptr )
  491. {
  492. initFromOther( aOther );
  493. }
  494. BOARD_DESIGN_SETTINGS& BOARD_DESIGN_SETTINGS::operator=( const BOARD_DESIGN_SETTINGS& aOther )
  495. {
  496. initFromOther( aOther );
  497. return *this;
  498. }
  499. void BOARD_DESIGN_SETTINGS::initFromOther( const BOARD_DESIGN_SETTINGS& aOther )
  500. {
  501. // Copy of NESTED_SETTINGS around is not allowed, so let's just update the params.
  502. m_TrackWidthList = aOther.m_TrackWidthList;
  503. m_ViasDimensionsList = aOther.m_ViasDimensionsList;
  504. m_DiffPairDimensionsList = aOther.m_DiffPairDimensionsList;
  505. m_MicroViasAllowed = aOther.m_MicroViasAllowed;
  506. m_BlindBuriedViaAllowed = aOther.m_BlindBuriedViaAllowed;
  507. m_CurrentViaType = aOther.m_CurrentViaType;
  508. m_UseConnectedTrackWidth = aOther.m_UseConnectedTrackWidth;
  509. m_MinClearance = aOther.m_MinClearance;
  510. m_TrackMinWidth = aOther.m_TrackMinWidth;
  511. m_ViasMinAnnulus = aOther.m_ViasMinAnnulus;
  512. m_ViasMinSize = aOther.m_ViasMinSize;
  513. m_MinThroughDrill = aOther.m_MinThroughDrill;
  514. m_MicroViasMinSize = aOther.m_MicroViasMinSize;
  515. m_MicroViasMinDrill = aOther.m_MicroViasMinDrill;
  516. m_CopperEdgeClearance = aOther.m_CopperEdgeClearance;
  517. m_HoleClearance = aOther.m_HoleClearance;
  518. m_HoleToHoleMin = aOther.m_HoleToHoleMin;
  519. m_SilkClearance = aOther.m_SilkClearance;
  520. m_DRCSeverities = aOther.m_DRCSeverities;
  521. m_DrcExclusions = aOther.m_DrcExclusions;
  522. m_ZoneFillVersion = aOther.m_ZoneFillVersion;
  523. m_ZoneKeepExternalFillets= aOther.m_ZoneKeepExternalFillets;
  524. m_MaxError = aOther.m_MaxError;
  525. m_SolderMaskMargin = aOther.m_SolderMaskMargin;
  526. m_SolderMaskMinWidth = aOther.m_SolderMaskMinWidth;
  527. m_SolderPasteMargin = aOther.m_SolderPasteMargin;
  528. m_SolderPasteMarginRatio = aOther.m_SolderPasteMarginRatio;
  529. m_DefaultFPTextItems = aOther.m_DefaultFPTextItems;
  530. std::copy( std::begin( aOther.m_LineThickness ), std::end( aOther.m_LineThickness ),
  531. std::begin( m_LineThickness ) );
  532. std::copy( std::begin( aOther.m_TextSize ), std::end( aOther.m_TextSize ),
  533. std::begin( m_TextSize ) );
  534. std::copy( std::begin( aOther.m_TextThickness ), std::end( aOther.m_TextThickness ),
  535. std::begin( m_TextThickness ) );
  536. std::copy( std::begin( aOther.m_TextItalic ), std::end( aOther.m_TextItalic ),
  537. std::begin( m_TextItalic ) );
  538. std::copy( std::begin( aOther.m_TextUpright ), std::end( aOther.m_TextUpright ),
  539. std::begin( m_TextUpright ) );
  540. m_DimensionUnitsMode = aOther.m_DimensionUnitsMode;
  541. m_DimensionPrecision = aOther.m_DimensionPrecision;
  542. m_DimensionUnitsFormat = aOther.m_DimensionUnitsFormat;
  543. m_DimensionSuppressZeroes = aOther.m_DimensionSuppressZeroes;
  544. m_DimensionTextPosition = aOther.m_DimensionTextPosition;
  545. m_DimensionKeepTextAligned = aOther.m_DimensionKeepTextAligned;
  546. m_DimensionArrowLength = aOther.m_DimensionArrowLength;
  547. m_DimensionExtensionOffset = aOther.m_DimensionExtensionOffset;
  548. m_AuxOrigin = aOther.m_AuxOrigin;
  549. m_GridOrigin = aOther.m_GridOrigin;
  550. m_HasStackup = aOther.m_HasStackup;
  551. m_trackWidthIndex = aOther.m_trackWidthIndex;
  552. m_viaSizeIndex = aOther.m_viaSizeIndex;
  553. m_diffPairIndex = aOther.m_diffPairIndex;
  554. m_useCustomTrackVia = aOther.m_useCustomTrackVia;
  555. m_customTrackWidth = aOther.m_customTrackWidth;
  556. m_customViaSize = aOther.m_customViaSize;
  557. m_useCustomDiffPair = aOther.m_useCustomDiffPair;
  558. m_customDiffPair = aOther.m_customDiffPair;
  559. m_copperLayerCount = aOther.m_copperLayerCount;
  560. m_enabledLayers = aOther.m_enabledLayers;
  561. m_boardThickness = aOther.m_boardThickness;
  562. m_currentNetClassName = aOther.m_currentNetClassName;
  563. m_stackup = aOther.m_stackup;
  564. // Only take the pointer from the other if it isn't the default
  565. if( aOther.m_netClasses == &aOther.m_internalNetClasses )
  566. m_netClasses = &m_internalNetClasses;
  567. else
  568. m_netClasses = aOther.m_netClasses;
  569. m_defaultZoneSettings = aOther.m_defaultZoneSettings;
  570. }
  571. bool BOARD_DESIGN_SETTINGS::migrateSchema0to1()
  572. {
  573. /**
  574. * Schema 0 to 1: default dimension precision changed in meaning.
  575. * Previously it was an enum with the following meaning:
  576. *
  577. * 0: 0.01mm / 1 mil / 0.001 in
  578. * 1: 0.001mm / 0.1 mil / 0.0001 in
  579. * 2: 0.0001mm / 0.01 mil / 0.00001 in
  580. *
  581. * Now it is indepenent of display units and is an integer meaning the number of digits
  582. * displayed after the decimal point, so we have to migrate based on the default units.
  583. *
  584. * The units is an integer with the following mapping:
  585. *
  586. * 0: Inches
  587. * 1: Mils
  588. * 2: Millimetres
  589. */
  590. nlohmann::json::json_pointer units_ptr( "/defaults/dimension_units" );
  591. nlohmann::json::json_pointer precision_ptr( "/defaults/dimension_precision" );
  592. if( !( contains( units_ptr ) && contains( precision_ptr ) &&
  593. at( units_ptr ).is_number_integer() &&
  594. at( precision_ptr ).is_number_integer() ) )
  595. {
  596. // if either is missing or invalid, migration doesn't make sense
  597. return true;
  598. }
  599. int units = at( units_ptr ).get<int>();
  600. int precision = at( precision_ptr ).get<int>();
  601. // The enum maps directly to precision if the units is mils
  602. int extraDigits = 0;
  603. switch( units )
  604. {
  605. case 0: extraDigits = 3; break;
  606. case 2: extraDigits = 2; break;
  607. default: break;
  608. }
  609. precision += extraDigits;
  610. ( *this )[precision_ptr] = precision;
  611. return true;
  612. }
  613. bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
  614. {
  615. bool ret = NESTED_SETTINGS::LoadFromFile( aDirectory );
  616. // A number of things won't have been translated by the PROJECT_FILE migration because of
  617. // descoped objects required to decode this data. So, it will be in the legacy.pcbnew
  618. // section and needs to be pulled out here
  619. PROJECT_FILE* project = dynamic_cast<PROJECT_FILE*>( GetParent() );
  620. if( !project )
  621. return ret;
  622. bool migrated = false;
  623. auto drcName =
  624. []( int aCode ) -> std::string
  625. {
  626. std::shared_ptr<DRC_ITEM> item = DRC_ITEM::Create( aCode );
  627. wxString name = item->GetSettingsKey();
  628. return std::string( name.ToUTF8() );
  629. };
  630. std::string bp = "board.design_settings.rule_severities.";
  631. std::string rs = "rule_severities.";
  632. if( OPT<bool> v =
  633. project->Get<bool>( PointerFromString( bp + "legacy_no_courtyard_defined" ) ) )
  634. {
  635. if( *v )
  636. ( *this )[PointerFromString( rs + drcName( DRCE_MISSING_COURTYARD ) )] = "error";
  637. else
  638. ( *this )[PointerFromString( rs + drcName( DRCE_MISSING_COURTYARD ) )] = "ignore";
  639. project->erase( PointerFromString( bp + "legacy_no_courtyard_defined" ) );
  640. migrated = true;
  641. }
  642. if( OPT<bool> v = project->Get<bool>( PointerFromString( bp + "legacy_courtyards_overlap" ) ) )
  643. {
  644. if( *v )
  645. ( *this )[PointerFromString( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ) )] = "error";
  646. else
  647. ( *this )[PointerFromString( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ) )] = "ignore";
  648. project->erase( PointerFromString( bp + "legacy_courtyards_overlap" ) );
  649. migrated = true;
  650. }
  651. if( project->contains( "legacy" ) )
  652. {
  653. // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
  654. // so we do the same for legacy boards.
  655. m_ZoneKeepExternalFillets = true;
  656. project->at( "legacy" ).erase( "pcbnew" );
  657. }
  658. // Now that we have everything, we need to load again
  659. if( migrated )
  660. Load();
  661. return ret;
  662. }
  663. SEVERITY BOARD_DESIGN_SETTINGS::GetSeverity( int aDRCErrorCode )
  664. {
  665. return m_DRCSeverities[ aDRCErrorCode ];
  666. }
  667. bool BOARD_DESIGN_SETTINGS::Ignore( int aDRCErrorCode )
  668. {
  669. return m_DRCSeverities[ aDRCErrorCode ] == RPT_SEVERITY_IGNORE;
  670. }
  671. int BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue()
  672. {
  673. int biggest = 0;
  674. DRC_CONSTRAINT constraint;
  675. if( m_DRCEngine )
  676. {
  677. m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
  678. biggest = std::max( biggest, constraint.Value().Min() );
  679. m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
  680. biggest = std::max( biggest, constraint.Value().Min() );
  681. m_DRCEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, constraint );
  682. biggest = std::max( biggest, constraint.Value().Min() );
  683. }
  684. return biggest;
  685. }
  686. int BOARD_DESIGN_SETTINGS::GetSmallestClearanceValue()
  687. {
  688. int clearance = GetDefault()->GetClearance();
  689. for( const std::pair<const wxString, NETCLASSPTR>& netclass : GetNetClasses().NetClasses() )
  690. clearance = std::min( clearance, netclass.second->GetClearance() );
  691. return clearance;
  692. }
  693. int BOARD_DESIGN_SETTINGS::GetCurrentMicroViaSize()
  694. {
  695. NETCLASSPTR netclass = GetNetClasses().Find( m_currentNetClassName );
  696. return netclass->GetuViaDiameter();
  697. }
  698. int BOARD_DESIGN_SETTINGS::GetCurrentMicroViaDrill()
  699. {
  700. NETCLASSPTR netclass = GetNetClasses().Find( m_currentNetClassName );
  701. return netclass->GetuViaDrill();
  702. }
  703. void BOARD_DESIGN_SETTINGS::SetViaSizeIndex( unsigned aIndex )
  704. {
  705. m_viaSizeIndex = std::min( aIndex, (unsigned) m_ViasDimensionsList.size() );
  706. m_useCustomTrackVia = false;
  707. }
  708. int BOARD_DESIGN_SETTINGS::GetCurrentViaSize() const
  709. {
  710. if( m_useCustomTrackVia )
  711. return m_customViaSize.m_Diameter;
  712. else if( m_viaSizeIndex == 0 )
  713. return GetNetClasses().GetDefaultPtr()->GetViaDiameter();
  714. else
  715. return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter;
  716. }
  717. int BOARD_DESIGN_SETTINGS::GetCurrentViaDrill() const
  718. {
  719. int drill;
  720. if( m_useCustomTrackVia )
  721. drill = m_customViaSize.m_Drill;
  722. else if( m_viaSizeIndex == 0 )
  723. drill = GetNetClasses().GetDefaultPtr()->GetViaDrill();
  724. else
  725. drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill;
  726. return drill > 0 ? drill : -1;
  727. }
  728. void BOARD_DESIGN_SETTINGS::SetTrackWidthIndex( unsigned aIndex )
  729. {
  730. m_trackWidthIndex = std::min( aIndex, (unsigned) m_TrackWidthList.size() );
  731. m_useCustomTrackVia = false;
  732. }
  733. int BOARD_DESIGN_SETTINGS::GetCurrentTrackWidth() const
  734. {
  735. if( m_useCustomTrackVia )
  736. return m_customTrackWidth;
  737. else if( m_trackWidthIndex == 0 )
  738. return GetNetClasses().GetDefaultPtr()->GetTrackWidth();
  739. else
  740. return m_TrackWidthList[ m_trackWidthIndex ];
  741. }
  742. void BOARD_DESIGN_SETTINGS::SetDiffPairIndex( unsigned aIndex )
  743. {
  744. m_diffPairIndex = std::min( aIndex, (unsigned) 8 );
  745. m_useCustomDiffPair = false;
  746. }
  747. void BOARD_DESIGN_SETTINGS::SetMinHoleSeparation( int aDistance )
  748. {
  749. m_HoleToHoleMin = aDistance;
  750. }
  751. void BOARD_DESIGN_SETTINGS::SetCopperEdgeClearance( int aDistance )
  752. {
  753. m_CopperEdgeClearance = aDistance;
  754. }
  755. void BOARD_DESIGN_SETTINGS::SetSilkClearance( int aDistance )
  756. {
  757. m_SilkClearance = aDistance;
  758. }
  759. void BOARD_DESIGN_SETTINGS::SetCopperLayerCount( int aNewLayerCount )
  760. {
  761. m_copperLayerCount = aNewLayerCount;
  762. // Update only enabled copper layers mask
  763. m_enabledLayers &= ~LSET::AllCuMask();
  764. if( aNewLayerCount > 0 )
  765. m_enabledLayers |= LSET::AllCuMask( aNewLayerCount );
  766. }
  767. void BOARD_DESIGN_SETTINGS::SetEnabledLayers( LSET aMask )
  768. {
  769. // Back and front layers are always enabled.
  770. aMask.set( B_Cu ).set( F_Cu );
  771. m_enabledLayers = aMask;
  772. // update m_CopperLayerCount to ensure its consistency with m_EnabledLayers
  773. m_copperLayerCount = ( aMask & LSET::AllCuMask() ).count();
  774. }
  775. // Return the layer class index { silk, copper, edges & courtyards, fab, others } of the
  776. // given layer.
  777. int BOARD_DESIGN_SETTINGS::GetLayerClass( PCB_LAYER_ID aLayer ) const
  778. {
  779. if( aLayer == F_SilkS || aLayer == B_SilkS )
  780. return LAYER_CLASS_SILK;
  781. else if( IsCopperLayer( aLayer ) )
  782. return LAYER_CLASS_COPPER;
  783. else if( aLayer == Edge_Cuts )
  784. return LAYER_CLASS_EDGES;
  785. else if( aLayer == F_CrtYd || aLayer == B_CrtYd )
  786. return LAYER_CLASS_COURTYARD;
  787. else if( aLayer == F_Fab || aLayer == B_Fab )
  788. return LAYER_CLASS_FAB;
  789. else
  790. return LAYER_CLASS_OTHERS;
  791. }
  792. int BOARD_DESIGN_SETTINGS::GetDRCEpsilon() const
  793. {
  794. return Millimeter2iu( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
  795. }
  796. int BOARD_DESIGN_SETTINGS::GetHolePlatingThickness() const
  797. {
  798. return Millimeter2iu( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
  799. }
  800. int BOARD_DESIGN_SETTINGS::GetLineThickness( PCB_LAYER_ID aLayer ) const
  801. {
  802. return m_LineThickness[ GetLayerClass( aLayer ) ];
  803. }
  804. wxSize BOARD_DESIGN_SETTINGS::GetTextSize( PCB_LAYER_ID aLayer ) const
  805. {
  806. return m_TextSize[ GetLayerClass( aLayer ) ];
  807. }
  808. int BOARD_DESIGN_SETTINGS::GetTextThickness( PCB_LAYER_ID aLayer ) const
  809. {
  810. return m_TextThickness[ GetLayerClass( aLayer ) ];
  811. }
  812. bool BOARD_DESIGN_SETTINGS::GetTextItalic( PCB_LAYER_ID aLayer ) const
  813. {
  814. return m_TextItalic[ GetLayerClass( aLayer ) ];
  815. }
  816. bool BOARD_DESIGN_SETTINGS::GetTextUpright( PCB_LAYER_ID aLayer ) const
  817. {
  818. return m_TextUpright[ GetLayerClass( aLayer ) ];
  819. }