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.

1506 lines
64 KiB

8 years ago
14 years ago
4 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-2023 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 <pcb_dimension.h>
  24. #include <pcb_track.h>
  25. #include <layer_ids.h>
  26. #include <kiface_base.h>
  27. #include <pad.h>
  28. #include <board_design_settings.h>
  29. #include <drc/drc_item.h>
  30. #include <drc/drc_engine.h>
  31. #include <settings/json_settings_internals.h>
  32. #include <settings/parameters.h>
  33. #include <project/project_file.h>
  34. #include <advanced_config.h>
  35. const int bdsSchemaVersion = 2;
  36. BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
  37. NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aParent, aPath )
  38. {
  39. // We want to leave alone parameters that aren't found in the project JSON as they may be
  40. // initialized by the board file parser before NESTED_SETTINGS::LoadFromFile is called.
  41. m_resetParamsIfMissing = false;
  42. // Create a default NET_SETTINGS so that things don't break horribly if there's no project
  43. // loaded. This also is used during file load for legacy boards that have netclasses stored
  44. // in the file. After load, this information will be moved to the project and the pointer
  45. // updated.
  46. m_NetSettings = std::make_shared<NET_SETTINGS>( nullptr, "" );
  47. m_HasStackup = false; // no stackup defined by default
  48. m_Pad_Master = std::make_unique<PAD>( nullptr );
  49. SetDefaultMasterPad();
  50. LSET all_set = LSET().set();
  51. m_enabledLayers = all_set; // All layers enabled at first.
  52. // SetCopperLayerCount() will adjust this.
  53. SetCopperLayerCount( 2 ); // Default design is a double sided board
  54. m_CurrentViaType = VIATYPE::THROUGH;
  55. // if true, when creating a new track starting on an existing track, use this track width
  56. m_UseConnectedTrackWidth = false;
  57. m_TempOverrideTrackWidth = false;
  58. // First is always the reference designator
  59. m_DefaultFPTextItems.emplace_back( wxT( "REF**" ), true, F_SilkS );
  60. // Second is always the value
  61. m_DefaultFPTextItems.emplace_back( wxT( "" ), true, F_Fab );
  62. // Any following ones are freebies
  63. m_DefaultFPTextItems.emplace_back( wxT( "${REFERENCE}" ), true, F_Fab );
  64. m_LineThickness[ LAYER_CLASS_SILK ] = pcbIUScale.mmToIU( DEFAULT_SILK_LINE_WIDTH );
  65. m_TextSize[ LAYER_CLASS_SILK ] = VECTOR2I( pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ),
  66. pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ) );
  67. m_TextThickness[ LAYER_CLASS_SILK ] = pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_WIDTH );
  68. m_TextItalic[ LAYER_CLASS_SILK ] = false;
  69. m_TextUpright[ LAYER_CLASS_SILK ] = false;
  70. m_LineThickness[ LAYER_CLASS_COPPER ] = pcbIUScale.mmToIU( DEFAULT_COPPER_LINE_WIDTH );
  71. m_TextSize[ LAYER_CLASS_COPPER ] = VECTOR2I( pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ),
  72. pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ) );
  73. m_TextThickness[ LAYER_CLASS_COPPER ] = pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_WIDTH );
  74. m_TextItalic[ LAYER_CLASS_COPPER ] = false;
  75. m_TextUpright[ LAYER_CLASS_COPPER ] = false;
  76. // Edges & Courtyards; text properties aren't used but better to have them holding
  77. // reasonable values than not.
  78. m_LineThickness[ LAYER_CLASS_EDGES ] = pcbIUScale.mmToIU( DEFAULT_EDGE_WIDTH );
  79. m_TextSize[ LAYER_CLASS_EDGES ] = VECTOR2I( pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
  80. pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
  81. m_TextThickness[ LAYER_CLASS_EDGES ] = pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH );
  82. m_TextItalic[ LAYER_CLASS_EDGES ] = false;
  83. m_TextUpright[ LAYER_CLASS_EDGES ] = false;
  84. m_LineThickness[ LAYER_CLASS_COURTYARD ] = pcbIUScale.mmToIU( DEFAULT_COURTYARD_WIDTH );
  85. m_TextSize[ LAYER_CLASS_COURTYARD ] = VECTOR2I( pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
  86. pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
  87. m_TextThickness[ LAYER_CLASS_COURTYARD ] = pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH );
  88. m_TextItalic[ LAYER_CLASS_COURTYARD ] = false;
  89. m_TextUpright[ LAYER_CLASS_COURTYARD ] = false;
  90. m_LineThickness[ LAYER_CLASS_FAB ] = pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH );
  91. m_TextSize[LAYER_CLASS_FAB] = VECTOR2I( pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
  92. pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
  93. m_TextThickness[ LAYER_CLASS_FAB ] = pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH );
  94. m_TextItalic[ LAYER_CLASS_FAB ] = false;
  95. m_TextUpright[ LAYER_CLASS_FAB ] = false;
  96. m_LineThickness[ LAYER_CLASS_OTHERS ] = pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH );
  97. m_TextSize[ LAYER_CLASS_OTHERS ] = VECTOR2I( pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
  98. pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ) );
  99. m_TextThickness[ LAYER_CLASS_OTHERS ] = pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH );
  100. m_TextItalic[ LAYER_CLASS_OTHERS ] = false;
  101. m_TextUpright[ LAYER_CLASS_OTHERS ] = false;
  102. m_StyleFPFields = false;
  103. m_StyleFPText = false;
  104. m_StyleFPShapes = false;
  105. m_DimensionPrecision = DIM_PRECISION::X_XXXX;
  106. m_DimensionUnitsMode = DIM_UNITS_MODE::AUTOMATIC;
  107. m_DimensionUnitsFormat = DIM_UNITS_FORMAT::BARE_SUFFIX;
  108. m_DimensionSuppressZeroes = false;
  109. m_DimensionTextPosition = DIM_TEXT_POSITION::OUTSIDE;
  110. m_DimensionKeepTextAligned = true;
  111. m_DimensionArrowLength = pcbIUScale.MilsToIU( DEFAULT_DIMENSION_ARROW_LENGTH );
  112. m_DimensionExtensionOffset = pcbIUScale.mmToIU( DEFAULT_DIMENSION_EXTENSION_OFFSET );
  113. m_useCustomTrackVia = false;
  114. m_customTrackWidth = pcbIUScale.mmToIU( DEFAULT_CUSTOMTRACKWIDTH );
  115. m_customViaSize.m_Diameter = pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE );
  116. m_customViaSize.m_Drill = pcbIUScale.mmToIU( DEFAULT_MINTHROUGHDRILL );
  117. m_useCustomDiffPair = false;
  118. m_customDiffPair.m_Width = pcbIUScale.mmToIU( DEFAULT_CUSTOMDPAIRWIDTH );
  119. m_customDiffPair.m_Gap = pcbIUScale.mmToIU( DEFAULT_CUSTOMDPAIRGAP );
  120. m_customDiffPair.m_ViaGap = pcbIUScale.mmToIU( DEFAULT_CUSTOMDPAIRVIAGAP );
  121. m_MinClearance = pcbIUScale.mmToIU( DEFAULT_MINCLEARANCE );
  122. m_MinConn = pcbIUScale.mmToIU( DEFAULT_MINCONNECTION );
  123. m_TrackMinWidth = pcbIUScale.mmToIU( DEFAULT_TRACKMINWIDTH );
  124. m_ViasMinAnnularWidth = pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE - DEFAULT_MINTHROUGHDRILL ) / 2;
  125. m_ViasMinSize = pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE );
  126. m_MinThroughDrill = pcbIUScale.mmToIU( DEFAULT_MINTHROUGHDRILL );
  127. m_MicroViasMinSize = pcbIUScale.mmToIU( DEFAULT_MICROVIASMINSIZE );
  128. m_MicroViasMinDrill = pcbIUScale.mmToIU( DEFAULT_MICROVIASMINDRILL );
  129. m_CopperEdgeClearance = pcbIUScale.mmToIU( DEFAULT_COPPEREDGECLEARANCE );
  130. m_HoleClearance = pcbIUScale.mmToIU( DEFAULT_HOLECLEARANCE );
  131. m_HoleToHoleMin = pcbIUScale.mmToIU( DEFAULT_HOLETOHOLEMIN );
  132. m_SilkClearance = pcbIUScale.mmToIU( DEFAULT_SILKCLEARANCE );
  133. m_MinResolvedSpokes = DEFAULT_MINRESOLVEDSPOKES;
  134. m_MinSilkTextHeight = pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE * 0.8 );
  135. m_MinSilkTextThickness= pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_WIDTH * 0.8 );
  136. for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode )
  137. m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
  138. m_DRCSeverities[ DRCE_DRILLED_HOLES_COLOCATED ] = RPT_SEVERITY_WARNING;
  139. m_DRCSeverities[ DRCE_DRILLED_HOLES_TOO_CLOSE ] = RPT_SEVERITY_WARNING;
  140. m_DRCSeverities[ DRCE_MISSING_COURTYARD ] = RPT_SEVERITY_IGNORE;
  141. m_DRCSeverities[ DRCE_PTH_IN_COURTYARD ] = RPT_SEVERITY_IGNORE;
  142. m_DRCSeverities[ DRCE_NPTH_IN_COURTYARD ] = RPT_SEVERITY_IGNORE;
  143. m_DRCSeverities[ DRCE_DANGLING_TRACK ] = RPT_SEVERITY_WARNING;
  144. m_DRCSeverities[ DRCE_DANGLING_VIA ] = RPT_SEVERITY_WARNING;
  145. m_DRCSeverities[ DRCE_COPPER_SLIVER ] = RPT_SEVERITY_WARNING;
  146. m_DRCSeverities[ DRCE_ISOLATED_COPPER ] = RPT_SEVERITY_WARNING;
  147. m_DRCSeverities[ DRCE_PADSTACK ] = RPT_SEVERITY_WARNING;
  148. m_DRCSeverities[ DRCE_MISSING_FOOTPRINT ] = RPT_SEVERITY_WARNING;
  149. m_DRCSeverities[ DRCE_DUPLICATE_FOOTPRINT ] = RPT_SEVERITY_WARNING;
  150. m_DRCSeverities[ DRCE_EXTRA_FOOTPRINT ] = RPT_SEVERITY_WARNING;
  151. m_DRCSeverities[ DRCE_NET_CONFLICT ] = RPT_SEVERITY_WARNING;
  152. m_DRCSeverities[ DRCE_SCHEMATIC_PARITY_ISSUES ] = RPT_SEVERITY_WARNING;
  153. m_DRCSeverities[ DRCE_OVERLAPPING_SILK ] = RPT_SEVERITY_WARNING;
  154. m_DRCSeverities[ DRCE_SILK_CLEARANCE ] = RPT_SEVERITY_WARNING;
  155. m_DRCSeverities[ DRCE_SILK_EDGE_CLEARANCE ] = RPT_SEVERITY_WARNING;
  156. m_DRCSeverities[ DRCE_TEXT_HEIGHT ] = RPT_SEVERITY_WARNING;
  157. m_DRCSeverities[ DRCE_TEXT_THICKNESS ] = RPT_SEVERITY_WARNING;
  158. m_DRCSeverities[ DRCE_FOOTPRINT_TYPE_MISMATCH ] = RPT_SEVERITY_IGNORE;
  159. m_DRCSeverities[ DRCE_LIB_FOOTPRINT_ISSUES ] = RPT_SEVERITY_WARNING;
  160. m_DRCSeverities[ DRCE_LIB_FOOTPRINT_MISMATCH ] = RPT_SEVERITY_WARNING;
  161. m_DRCSeverities[ DRCE_CONNECTION_WIDTH ] = RPT_SEVERITY_WARNING;
  162. m_MaxError = ARC_HIGH_DEF;
  163. m_ZoneKeepExternalFillets = false;
  164. m_UseHeightForLengthCalcs = true;
  165. // Global mask margins:
  166. m_SolderMaskExpansion = pcbIUScale.mmToIU( DEFAULT_SOLDERMASK_EXPANSION );
  167. m_SolderMaskMinWidth = pcbIUScale.mmToIU( DEFAULT_SOLDERMASK_MIN_WIDTH );
  168. m_SolderMaskToCopperClearance = pcbIUScale.mmToIU( DEFAULT_SOLDERMASK_TO_COPPER_CLEARANCE );
  169. // Solder paste margin absolute value
  170. m_SolderPasteMargin = pcbIUScale.mmToIU( DEFAULT_SOLDERPASTE_CLEARANCE );
  171. // Solder paste margin as a ratio of pad size
  172. // The final margin is the sum of these 2 values
  173. // Usually < 0 because the mask is smaller than pad
  174. m_SolderPasteMarginRatio = DEFAULT_SOLDERPASTE_RATIO;
  175. m_AllowSoldermaskBridgesInFPs = false;
  176. m_TentViasFront = true;
  177. m_TentViasBack = true;
  178. // Layer thickness for 3D viewer
  179. m_boardThickness = pcbIUScale.mmToIU( DEFAULT_BOARD_THICKNESS_MM );
  180. // Default spacing for meanders
  181. m_SingleTrackMeanderSettings.m_spacing = pcbIUScale.mmToIU( DEFAULT_MEANDER_SPACING );
  182. m_SkewMeanderSettings.m_spacing = pcbIUScale.mmToIU( DEFAULT_MEANDER_SPACING );
  183. m_DiffPairMeanderSettings.m_spacing = pcbIUScale.mmToIU( DEFAULT_DP_MEANDER_SPACING );
  184. m_viaSizeIndex = 0;
  185. m_trackWidthIndex = 0;
  186. m_diffPairIndex = 0;
  187. // Parameters stored in JSON in the project file
  188. // NOTE: Previously, BOARD_DESIGN_SETTINGS stored the basic board layer information (layer
  189. // names and enable/disable state) in the project file even though this information is also
  190. // stored in the board file. This was implemented for importing these settings from another
  191. // project. Going forward, the import feature will just import from other board files (since
  192. // we could have multi-board projects in the future anyway) so this functionality is dropped.
  193. m_params.emplace_back( new PARAM<bool>( "rules.use_height_for_length_calcs",
  194. &m_UseHeightForLengthCalcs, true ) );
  195. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_clearance",
  196. &m_MinClearance, pcbIUScale.mmToIU( DEFAULT_MINCLEARANCE ),
  197. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
  198. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_connection",
  199. &m_MinConn, pcbIUScale.mmToIU( DEFAULT_MINCONNECTION ),
  200. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
  201. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_track_width",
  202. &m_TrackMinWidth, pcbIUScale.mmToIU( DEFAULT_TRACKMINWIDTH ),
  203. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
  204. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_annular_width",
  205. &m_ViasMinAnnularWidth, pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE ),
  206. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
  207. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_diameter",
  208. &m_ViasMinSize, pcbIUScale.mmToIU( DEFAULT_VIASMINSIZE ),
  209. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
  210. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_through_hole_diameter",
  211. &m_MinThroughDrill, pcbIUScale.mmToIU( DEFAULT_MINTHROUGHDRILL ),
  212. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
  213. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_diameter",
  214. &m_MicroViasMinSize, pcbIUScale.mmToIU( DEFAULT_MICROVIASMINSIZE ),
  215. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
  216. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_drill",
  217. &m_MicroViasMinDrill, pcbIUScale.mmToIU( DEFAULT_MICROVIASMINDRILL ),
  218. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
  219. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_to_hole",
  220. &m_HoleToHoleMin, pcbIUScale.mmToIU( DEFAULT_HOLETOHOLEMIN ),
  221. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 10.0 ), pcbIUScale.MM_PER_IU ) );
  222. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_clearance",
  223. &m_HoleClearance, pcbIUScale.mmToIU( DEFAULT_HOLECLEARANCE ),
  224. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
  225. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_silk_clearance",
  226. &m_SilkClearance, pcbIUScale.mmToIU( DEFAULT_SILKCLEARANCE ),
  227. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
  228. // While the maximum *effective* value is 4, we've had users interpret this as the count on
  229. // all layers, and enter something like 10. They'll figure it out soon enough *unless* we
  230. // enforce a max of 4 (and therefore reset it back to the default of 2), at which point it
  231. // just looks buggy.
  232. m_params.emplace_back( new PARAM<int>( "rules.min_resolved_spokes",
  233. &m_MinResolvedSpokes, DEFAULT_MINRESOLVEDSPOKES, 0, 99 ) );
  234. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_height",
  235. &m_MinSilkTextHeight, pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE * 0.8 ),
  236. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 100.0 ), pcbIUScale.MM_PER_IU ) );
  237. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_text_thickness",
  238. &m_MinSilkTextThickness, pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_WIDTH * 0.8 ),
  239. pcbIUScale.mmToIU( 0.00 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
  240. // Note: a clearance of -0.01 is a flag indicating we should use the legacy (pre-6.0) method
  241. // based on the edge cut thicknesses.
  242. m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_copper_edge_clearance",
  243. &m_CopperEdgeClearance, pcbIUScale.mmToIU( DEFAULT_COPPEREDGECLEARANCE ),
  244. pcbIUScale.mmToIU( -0.01 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
  245. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
  246. [&]() -> nlohmann::json
  247. {
  248. nlohmann::json ret = {};
  249. for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
  250. {
  251. wxString name = item.GetSettingsKey();
  252. int code = item.GetErrorCode();
  253. if( name.IsEmpty() || m_DRCSeverities.count( code ) == 0 )
  254. continue;
  255. ret[std::string( name.ToUTF8() )] = SeverityToString( m_DRCSeverities[code] );
  256. }
  257. return ret;
  258. },
  259. [&]( const nlohmann::json& aJson )
  260. {
  261. if( !aJson.is_object() )
  262. return;
  263. for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
  264. {
  265. wxString name = item.GetSettingsKey();
  266. std::string key( name.ToUTF8() );
  267. if( aJson.contains( key ) )
  268. m_DRCSeverities[item.GetErrorCode()] = SeverityFromString( aJson[key] );
  269. }
  270. }, {} ) );
  271. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "drc_exclusions",
  272. [&]() -> nlohmann::json
  273. {
  274. nlohmann::json js = nlohmann::json::array();
  275. for( const wxString& entry : m_DrcExclusions )
  276. js.push_back( { entry, m_DrcExclusionComments[ entry ] } );
  277. return js;
  278. },
  279. [&]( const nlohmann::json& aObj )
  280. {
  281. m_DrcExclusions.clear();
  282. if( !aObj.is_array() )
  283. return;
  284. for( const nlohmann::json& entry : aObj )
  285. {
  286. if( entry.is_array() )
  287. {
  288. wxString serialized = entry[0].get<wxString>();
  289. m_DrcExclusions.insert( serialized );
  290. m_DrcExclusionComments[ serialized ] = entry[1].get<wxString>();
  291. }
  292. else if( entry.is_string() )
  293. {
  294. m_DrcExclusions.insert( entry.get<wxString>() );
  295. }
  296. }
  297. },
  298. {} ) );
  299. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "track_widths",
  300. [&]() -> nlohmann::json
  301. {
  302. nlohmann::json js = nlohmann::json::array();
  303. for( const int& width : m_TrackWidthList )
  304. js.push_back( pcbIUScale.IUTomm( width ) );
  305. return js;
  306. },
  307. [&]( const nlohmann::json& aJson )
  308. {
  309. if( !aJson.is_array() )
  310. return;
  311. m_TrackWidthList.clear();
  312. for( const nlohmann::json& entry : aJson )
  313. {
  314. if( entry.empty() )
  315. continue;
  316. m_TrackWidthList.emplace_back( pcbIUScale.mmToIU( entry.get<double>() ) );
  317. }
  318. },
  319. {} ) );
  320. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "via_dimensions",
  321. [&]() -> nlohmann::json
  322. {
  323. nlohmann::json js = nlohmann::json::array();
  324. for( const auto& via : m_ViasDimensionsList )
  325. {
  326. nlohmann::json entry = {};
  327. entry["diameter"] = pcbIUScale.IUTomm( via.m_Diameter );
  328. entry["drill"] = pcbIUScale.IUTomm( via.m_Drill );
  329. js.push_back( entry );
  330. }
  331. return js;
  332. },
  333. [&]( const nlohmann::json& aObj )
  334. {
  335. if( !aObj.is_array() )
  336. return;
  337. m_ViasDimensionsList.clear();
  338. for( const nlohmann::json& entry : aObj )
  339. {
  340. if( entry.empty() || !entry.is_object() )
  341. continue;
  342. if( !entry.contains( "diameter" ) || !entry.contains( "drill" ) )
  343. continue;
  344. int diameter = pcbIUScale.mmToIU( entry["diameter"].get<double>() );
  345. int drill = pcbIUScale.mmToIU( entry["drill"].get<double>() );
  346. m_ViasDimensionsList.emplace_back( VIA_DIMENSION( diameter, drill ) );
  347. }
  348. },
  349. {} ) );
  350. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "diff_pair_dimensions",
  351. [&]() -> nlohmann::json
  352. {
  353. nlohmann::json js = nlohmann::json::array();
  354. for( const auto& pair : m_DiffPairDimensionsList )
  355. {
  356. nlohmann::json entry = {};
  357. entry["width"] = pcbIUScale.IUTomm( pair.m_Width );
  358. entry["gap"] = pcbIUScale.IUTomm( pair.m_Gap );
  359. entry["via_gap"] = pcbIUScale.IUTomm( pair.m_ViaGap );
  360. js.push_back( entry );
  361. }
  362. return js;
  363. },
  364. [&]( const nlohmann::json& aObj )
  365. {
  366. if( !aObj.is_array() )
  367. return;
  368. m_DiffPairDimensionsList.clear();
  369. for( const nlohmann::json& entry : aObj )
  370. {
  371. if( entry.empty() || !entry.is_object() )
  372. continue;
  373. if( !entry.contains( "width" ) || !entry.contains( "gap" )
  374. || !entry.contains( "via_gap" ) )
  375. continue;
  376. int width = pcbIUScale.mmToIU( entry["width"].get<double>() );
  377. int gap = pcbIUScale.mmToIU( entry["gap"].get<double>() );
  378. int via_gap = pcbIUScale.mmToIU( entry["via_gap"].get<double>() );
  379. m_DiffPairDimensionsList.emplace_back(
  380. DIFF_PAIR_DIMENSION( width, gap, via_gap ) );
  381. }
  382. },
  383. {} ) );
  384. // Handle options for teardrops (targets and some others):
  385. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_options",
  386. [&]() -> nlohmann::json
  387. {
  388. nlohmann::json js = nlohmann::json::array();
  389. nlohmann::json entry = {};
  390. entry["td_onviapad"] = m_TeardropParamsList.m_TargetViasPads;
  391. entry["td_onpadsmd"] = m_TeardropParamsList.m_TargetPadsWithNoHole;
  392. entry["td_ontrackend"] = m_TeardropParamsList.m_TargetTrack2Track;
  393. entry["td_onroundshapesonly"] = m_TeardropParamsList.m_UseRoundShapesOnly;
  394. js.push_back( entry );
  395. return js;
  396. },
  397. [&]( const nlohmann::json& aObj )
  398. {
  399. if( !aObj.is_array() )
  400. return;
  401. for( const nlohmann::json& entry : aObj )
  402. {
  403. if( entry.empty() || !entry.is_object() )
  404. continue;
  405. if( entry.contains( "td_onviapad" ) )
  406. m_TeardropParamsList.m_TargetViasPads = entry["td_onviapad"].get<bool>();
  407. if( entry.contains( "td_onpadsmd" ) )
  408. m_TeardropParamsList.m_TargetPadsWithNoHole = entry["td_onpadsmd"].get<bool>();
  409. if( entry.contains( "td_ontrackend" ) )
  410. m_TeardropParamsList.m_TargetTrack2Track = entry["td_ontrackend"].get<bool>();
  411. if( entry.contains( "td_onroundshapesonly" ) )
  412. m_TeardropParamsList.m_UseRoundShapesOnly = entry["td_onroundshapesonly"].get<bool>();
  413. // Legacy settings
  414. for( int ii = 0; ii < 3; ++ii )
  415. {
  416. TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)ii );
  417. if( entry.contains( "td_allow_use_two_tracks" ) )
  418. td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
  419. if( entry.contains( "td_curve_segcount" ) )
  420. td_prm->m_CurveSegCount = entry["td_curve_segcount"].get<int>();
  421. if( entry.contains( "td_on_pad_in_zone" ) )
  422. td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
  423. }
  424. }
  425. },
  426. {} ) );
  427. // Handle parameters (sizes, shape) for each type of teardrop:
  428. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "teardrop_parameters",
  429. [&]() -> nlohmann::json
  430. {
  431. nlohmann::json js = nlohmann::json::array();
  432. for( size_t ii = 0; ii < m_TeardropParamsList.GetParametersCount(); ii++ )
  433. {
  434. nlohmann::json entry = {};
  435. TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)ii );
  436. entry["td_target_name"] = GetTeardropTargetCanonicalName( (TARGET_TD)ii );
  437. entry["td_maxlen"] = pcbIUScale.IUTomm( td_prm->m_TdMaxLen );
  438. entry["td_maxheight"] = pcbIUScale.IUTomm( td_prm->m_TdMaxWidth );
  439. entry["td_length_ratio"] = td_prm->m_BestLengthRatio;
  440. entry["td_height_ratio"] = td_prm->m_BestWidthRatio;
  441. entry["td_curve_segcount"] = td_prm->m_CurveSegCount;
  442. entry["td_width_to_size_filter_ratio"] = td_prm->m_WidthtoSizeFilterRatio;
  443. entry["td_allow_use_two_tracks"] = td_prm->m_AllowUseTwoTracks;
  444. entry["td_curve_segcount"] = td_prm->m_CurveSegCount;
  445. entry["td_on_pad_in_zone"] = td_prm->m_TdOnPadsInZones;
  446. js.push_back( entry );
  447. }
  448. return js;
  449. },
  450. [&]( const nlohmann::json& aObj )
  451. {
  452. if( !aObj.is_array() )
  453. return;
  454. for( const nlohmann::json& entry : aObj )
  455. {
  456. if( entry.empty() || !entry.is_object() )
  457. continue;
  458. if( !entry.contains( "td_target_name" ) )
  459. continue;
  460. int idx = GetTeardropTargetTypeFromCanonicalName( entry["td_target_name"].get<std::string>() );
  461. if( idx >= 0 && idx < 3 )
  462. {
  463. TEARDROP_PARAMETERS* td_prm = m_TeardropParamsList.GetParameters( (TARGET_TD)idx );
  464. if( entry.contains( "td_maxlen" ) )
  465. td_prm->m_TdMaxLen = pcbIUScale.mmToIU( entry["td_maxlen"].get<double>() );
  466. if( entry.contains( "td_maxheight" ) )
  467. td_prm->m_TdMaxWidth = pcbIUScale.mmToIU( entry["td_maxheight"].get<double>() );
  468. if( entry.contains( "td_length_ratio" ) )
  469. td_prm->m_BestLengthRatio = entry["td_length_ratio"].get<double>();
  470. if( entry.contains( "td_height_ratio" ) )
  471. td_prm->m_BestWidthRatio = entry["td_height_ratio"].get<double>();
  472. if( entry.contains( "td_curve_segcount" ) )
  473. td_prm->m_CurveSegCount = entry["td_curve_segcount"].get<int>();
  474. if( entry.contains( "td_width_to_size_filter_ratio" ) )
  475. td_prm->m_WidthtoSizeFilterRatio = entry["td_width_to_size_filter_ratio"].get<double>();
  476. if( entry.contains( "td_allow_use_two_tracks" ) )
  477. td_prm->m_AllowUseTwoTracks = entry["td_allow_use_two_tracks"].get<bool>();
  478. if( entry.contains( "td_curve_segcount" ) )
  479. td_prm->m_CurveSegCount = entry["td_curve_segcount"].get<int>();
  480. if( entry.contains( "td_on_pad_in_zone" ) )
  481. td_prm->m_TdOnPadsInZones = entry["td_on_pad_in_zone"].get<bool>();
  482. }
  483. }
  484. },
  485. {} ) );
  486. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "tuning_pattern_settings",
  487. [&]() -> nlohmann::json
  488. {
  489. nlohmann::json js = {};
  490. auto make_settings =
  491. []( const PNS::MEANDER_SETTINGS& aSettings )
  492. {
  493. nlohmann::json entry = {};
  494. entry["min_amplitude"] = pcbIUScale.IUTomm( aSettings.m_minAmplitude );
  495. entry["max_amplitude"] = pcbIUScale.IUTomm( aSettings.m_maxAmplitude );
  496. entry["spacing"] = pcbIUScale.IUTomm( aSettings.m_spacing );
  497. entry["corner_style"] = aSettings.m_cornerStyle == PNS::MEANDER_STYLE_CHAMFER ? 0 : 1;
  498. entry["corner_radius_percentage"] = aSettings.m_cornerRadiusPercentage;
  499. entry["single_sided"] = aSettings.m_singleSided;
  500. return entry;
  501. };
  502. js["single_track_defaults"] = make_settings( m_SingleTrackMeanderSettings );
  503. js["diff_pair_defaults"] = make_settings( m_DiffPairMeanderSettings );
  504. js["diff_pair_skew_defaults"] = make_settings( m_SkewMeanderSettings );
  505. return js;
  506. },
  507. [&]( const nlohmann::json& aObj )
  508. {
  509. auto read_settings =
  510. []( const nlohmann::json& entry ) -> PNS::MEANDER_SETTINGS
  511. {
  512. PNS::MEANDER_SETTINGS settings;
  513. if( entry.contains( "min_amplitude" ) )
  514. settings.m_minAmplitude = pcbIUScale.mmToIU( entry["min_amplitude"].get<double>() );
  515. if( entry.contains( "max_amplitude" ) )
  516. settings.m_maxAmplitude = pcbIUScale.mmToIU( entry["max_amplitude"].get<double>() );
  517. if( entry.contains( "spacing" ) )
  518. settings.m_spacing = pcbIUScale.mmToIU( entry["spacing"].get<double>() );
  519. if( entry.contains( "corner_style" ) )
  520. {
  521. settings.m_cornerStyle = entry["corner_style"] == 0 ? PNS::MEANDER_STYLE_CHAMFER
  522. : PNS::MEANDER_STYLE_ROUND;
  523. }
  524. if( entry.contains( "corner_radius_percentage" ) )
  525. settings.m_cornerRadiusPercentage = entry["corner_radius_percentage"].get<int>();
  526. if( entry.contains( "single_sided" ) )
  527. settings.m_singleSided = entry["single_sided"].get<bool>();
  528. return settings;
  529. };
  530. if( aObj.contains( "single_track_defaults" ) )
  531. m_SingleTrackMeanderSettings = read_settings( aObj["single_track_defaults"] );
  532. if( aObj.contains( "diff_pair_defaults" ) )
  533. m_DiffPairMeanderSettings = read_settings( aObj["diff_pair_defaults"] );
  534. if( aObj.contains( "diff_pair_skew_defaults" ) )
  535. m_SkewMeanderSettings = read_settings( aObj["diff_pair_skew_defaults"] );
  536. },
  537. {} ) );
  538. int minTextSize = pcbIUScale.mmToIU( TEXT_MIN_SIZE_MM );
  539. int maxTextSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
  540. int minStroke = 1;
  541. int maxStroke = pcbIUScale.mmToIU( 100 );
  542. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_line_width",
  543. &m_LineThickness[LAYER_CLASS_SILK], pcbIUScale.mmToIU( DEFAULT_SILK_LINE_WIDTH ),
  544. minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  545. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_v",
  546. &m_TextSize[LAYER_CLASS_SILK].y, pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ),
  547. minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  548. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_h",
  549. &m_TextSize[LAYER_CLASS_SILK].x, pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ),
  550. minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  551. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_thickness",
  552. &m_TextThickness[LAYER_CLASS_SILK], pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_WIDTH ),
  553. minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  554. m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_italic",
  555. &m_TextItalic[LAYER_CLASS_SILK], false ) );
  556. m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_upright",
  557. &m_TextUpright[ LAYER_CLASS_SILK ], true ) );
  558. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_line_width",
  559. &m_LineThickness[LAYER_CLASS_COPPER], pcbIUScale.mmToIU( DEFAULT_COPPER_LINE_WIDTH ),
  560. minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  561. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_v",
  562. &m_TextSize[LAYER_CLASS_COPPER].y, pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ),
  563. minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  564. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_h",
  565. &m_TextSize[LAYER_CLASS_COPPER].x, pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ),
  566. minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  567. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_thickness",
  568. &m_TextThickness[LAYER_CLASS_COPPER], pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_WIDTH ),
  569. minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  570. m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_italic",
  571. &m_TextItalic[LAYER_CLASS_COPPER], false ) );
  572. m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_upright",
  573. &m_TextUpright[LAYER_CLASS_COPPER], true ) );
  574. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.board_outline_line_width",
  575. &m_LineThickness[LAYER_CLASS_EDGES], pcbIUScale.mmToIU( DEFAULT_EDGE_WIDTH ),
  576. minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  577. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.courtyard_line_width",
  578. &m_LineThickness[LAYER_CLASS_COURTYARD], pcbIUScale.mmToIU( DEFAULT_COURTYARD_WIDTH ),
  579. minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  580. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_line_width",
  581. &m_LineThickness[LAYER_CLASS_FAB], pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ),
  582. minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  583. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_v",
  584. &m_TextSize[LAYER_CLASS_FAB].y, pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
  585. minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  586. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_h",
  587. &m_TextSize[LAYER_CLASS_FAB].x, pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
  588. minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  589. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_thickness",
  590. &m_TextThickness[LAYER_CLASS_FAB], pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH ),
  591. minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  592. m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_italic",
  593. &m_TextItalic[LAYER_CLASS_FAB], false ) );
  594. m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_upright",
  595. &m_TextUpright[LAYER_CLASS_FAB], true ) );
  596. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_line_width",
  597. &m_LineThickness[LAYER_CLASS_OTHERS], pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ),
  598. minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  599. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_v",
  600. &m_TextSize[LAYER_CLASS_OTHERS].y, pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
  601. minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  602. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_h",
  603. &m_TextSize[LAYER_CLASS_OTHERS].x, pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ),
  604. minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
  605. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_thickness",
  606. &m_TextThickness[LAYER_CLASS_OTHERS], pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH ),
  607. minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
  608. m_params.emplace_back( new PARAM<bool>( "defaults.other_text_italic",
  609. &m_TextItalic[LAYER_CLASS_OTHERS], false ) );
  610. m_params.emplace_back( new PARAM<bool>( "defaults.other_text_upright",
  611. &m_TextUpright[LAYER_CLASS_OTHERS], true ) );
  612. m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_MODE>( "defaults.dimension_units",
  613. &m_DimensionUnitsMode, DIM_UNITS_MODE::AUTOMATIC, DIM_UNITS_MODE::INCHES,
  614. DIM_UNITS_MODE::AUTOMATIC ) );
  615. m_params.emplace_back( new PARAM_ENUM<DIM_PRECISION>( "defaults.dimension_precision",
  616. &m_DimensionPrecision, DIM_PRECISION::X_XXXX, DIM_PRECISION::X, DIM_PRECISION::V_VVVVV ) );
  617. m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_FORMAT>( "defaults.dimensions.units_format",
  618. &m_DimensionUnitsFormat, DIM_UNITS_FORMAT::BARE_SUFFIX, DIM_UNITS_FORMAT::NO_SUFFIX,
  619. DIM_UNITS_FORMAT::PAREN_SUFFIX ) );
  620. m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.suppress_zeroes",
  621. &m_DimensionSuppressZeroes, false ) );
  622. // NOTE: excluding DIM_TEXT_POSITION::MANUAL from the valid range here
  623. m_params.emplace_back( new PARAM_ENUM<DIM_TEXT_POSITION>( "defaults.dimensions.text_position",
  624. &m_DimensionTextPosition, DIM_TEXT_POSITION::OUTSIDE, DIM_TEXT_POSITION::OUTSIDE,
  625. DIM_TEXT_POSITION::INLINE ) );
  626. m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.keep_text_aligned",
  627. &m_DimensionKeepTextAligned, true ) );
  628. m_params.emplace_back( new PARAM<int>( "defaults.dimensions.arrow_length",
  629. &m_DimensionArrowLength,
  630. pcbIUScale.MilsToIU( DEFAULT_DIMENSION_ARROW_LENGTH ) ) );
  631. m_params.emplace_back( new PARAM<int>( "defaults.dimensions.extension_offset",
  632. &m_DimensionExtensionOffset,
  633. pcbIUScale.mmToIU( DEFAULT_DIMENSION_EXTENSION_OFFSET ) ) );
  634. m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_fields",
  635. &m_StyleFPFields, false ) );
  636. m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_text",
  637. &m_StyleFPText, false ) );
  638. m_params.emplace_back( new PARAM<bool>( "defaults.apply_defaults_to_fp_shapes",
  639. &m_StyleFPShapes, false ) );
  640. m_params.emplace_back( new PARAM_SCALED<int>( "defaults.zones.min_clearance",
  641. &m_defaultZoneSettings.m_ZoneClearance, pcbIUScale.mmToIU( ZONE_CLEARANCE_MM ),
  642. pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
  643. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "defaults.pads",
  644. [&]() -> nlohmann::json
  645. {
  646. nlohmann::json ret =
  647. {
  648. { "width", pcbIUScale.IUTomm( m_Pad_Master->GetSize().x ) },
  649. { "height", pcbIUScale.IUTomm( m_Pad_Master->GetSize().y ) },
  650. { "drill", pcbIUScale.IUTomm( m_Pad_Master->GetDrillSize().x ) }
  651. };
  652. return ret;
  653. },
  654. [&]( const nlohmann::json& aJson )
  655. {
  656. if( aJson.contains( "width" ) && aJson.contains( "height" )
  657. && aJson.contains( "drill" ) )
  658. {
  659. VECTOR2I sz;
  660. sz.x = pcbIUScale.mmToIU( aJson["width"].get<double>() );
  661. sz.y = pcbIUScale.mmToIU( aJson["height"].get<double>() );
  662. m_Pad_Master->SetSize( sz );
  663. int drill = pcbIUScale.mmToIU( aJson["drill"].get<double>() );
  664. m_Pad_Master->SetDrillSize( VECTOR2I( drill, drill ) );
  665. }
  666. }, {} ) );
  667. m_params.emplace_back( new PARAM_SCALED<int>( "rules.max_error",
  668. &m_MaxError, ARC_HIGH_DEF, pcbIUScale.mmToIU( 0.0001 ), pcbIUScale.mmToIU( 1.0 ), pcbIUScale.MM_PER_IU ) );
  669. m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_mask_to_copper_clearance",
  670. &m_SolderMaskToCopperClearance, pcbIUScale.mmToIU( DEFAULT_SOLDERMASK_TO_COPPER_CLEARANCE ),
  671. pcbIUScale.mmToIU( 0.0 ), pcbIUScale.mmToIU( 25.0 ), pcbIUScale.MM_PER_IU ) );
  672. m_params.emplace_back( new PARAM<bool>( "zones_allow_external_fillets",
  673. &m_ZoneKeepExternalFillets, false ) );
  674. registerMigration( 0, 1, std::bind( &BOARD_DESIGN_SETTINGS::migrateSchema0to1, this ) );
  675. registerMigration( 1, 2,
  676. [&]() -> bool
  677. {
  678. // Schema 1 to 2: move mask and paste margin settings back to board.
  679. // The parameters are removed, so we just have to manually load them here and
  680. // they will get saved with the board
  681. if( std::optional<double> optval = Get<double>( "rules.solder_mask_clearance" ) )
  682. m_SolderMaskExpansion = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
  683. if( std::optional<double> optval = Get<double>( "rules.solder_mask_min_width" ) )
  684. m_SolderMaskMinWidth = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
  685. if( std::optional<double> optval = Get<double>( "rules.solder_paste_clearance" ) )
  686. m_SolderPasteMargin = static_cast<int>( *optval * pcbIUScale.IU_PER_MM );
  687. if( std::optional<double> optval = Get<double>( "rules.solder_paste_margin_ratio" ) )
  688. m_SolderPasteMarginRatio = *optval;
  689. try
  690. {
  691. At( "rules" ).erase( "solder_mask_clearance" );
  692. At( "rules" ).erase( "solder_mask_min_width" );
  693. At( "rules" ).erase( "solder_paste_clearance" );
  694. At( "rules" ).erase( "solder_paste_margin_ratio" );
  695. }
  696. catch( ... )
  697. {}
  698. return true;
  699. } );
  700. }
  701. BOARD_DESIGN_SETTINGS::~BOARD_DESIGN_SETTINGS()
  702. {
  703. if( m_parent )
  704. {
  705. m_parent->ReleaseNestedSettings( this );
  706. m_parent = nullptr;
  707. }
  708. }
  709. BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( const BOARD_DESIGN_SETTINGS& aOther ) :
  710. NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aOther.m_parent,
  711. aOther.m_path ),
  712. m_Pad_Master( nullptr )
  713. {
  714. initFromOther( aOther );
  715. }
  716. BOARD_DESIGN_SETTINGS& BOARD_DESIGN_SETTINGS::operator=( const BOARD_DESIGN_SETTINGS& aOther )
  717. {
  718. initFromOther( aOther );
  719. return *this;
  720. }
  721. void BOARD_DESIGN_SETTINGS::initFromOther( const BOARD_DESIGN_SETTINGS& aOther )
  722. {
  723. // Copy of NESTED_SETTINGS around is not allowed, so let's just update the params.
  724. m_TrackWidthList = aOther.m_TrackWidthList;
  725. m_ViasDimensionsList = aOther.m_ViasDimensionsList;
  726. m_DiffPairDimensionsList = aOther.m_DiffPairDimensionsList;
  727. m_CurrentViaType = aOther.m_CurrentViaType;
  728. m_UseConnectedTrackWidth = aOther.m_UseConnectedTrackWidth;
  729. m_TempOverrideTrackWidth = aOther.m_TempOverrideTrackWidth;
  730. m_MinClearance = aOther.m_MinClearance;
  731. m_MinConn = aOther.m_MinConn;
  732. m_TrackMinWidth = aOther.m_TrackMinWidth;
  733. m_ViasMinAnnularWidth = aOther.m_ViasMinAnnularWidth;
  734. m_ViasMinSize = aOther.m_ViasMinSize;
  735. m_MinThroughDrill = aOther.m_MinThroughDrill;
  736. m_MicroViasMinSize = aOther.m_MicroViasMinSize;
  737. m_MicroViasMinDrill = aOther.m_MicroViasMinDrill;
  738. m_CopperEdgeClearance = aOther.m_CopperEdgeClearance;
  739. m_HoleClearance = aOther.m_HoleClearance;
  740. m_HoleToHoleMin = aOther.m_HoleToHoleMin;
  741. m_SilkClearance = aOther.m_SilkClearance;
  742. m_MinResolvedSpokes = aOther.m_MinResolvedSpokes;
  743. m_MinSilkTextHeight = aOther.m_MinSilkTextHeight;
  744. m_MinSilkTextThickness = aOther.m_MinSilkTextThickness;
  745. m_DRCSeverities = aOther.m_DRCSeverities;
  746. m_DrcExclusions = aOther.m_DrcExclusions;
  747. m_DrcExclusionComments = aOther.m_DrcExclusionComments;
  748. m_ZoneKeepExternalFillets = aOther.m_ZoneKeepExternalFillets;
  749. m_MaxError = aOther.m_MaxError;
  750. m_SolderMaskExpansion = aOther.m_SolderMaskExpansion;
  751. m_SolderMaskMinWidth = aOther.m_SolderMaskMinWidth;
  752. m_SolderMaskToCopperClearance = aOther.m_SolderMaskToCopperClearance;
  753. m_SolderPasteMargin = aOther.m_SolderPasteMargin;
  754. m_SolderPasteMarginRatio = aOther.m_SolderPasteMarginRatio;
  755. m_AllowSoldermaskBridgesInFPs = aOther.m_AllowSoldermaskBridgesInFPs;
  756. m_TentViasFront = aOther.m_TentViasFront;
  757. m_TentViasBack = aOther.m_TentViasBack;
  758. m_DefaultFPTextItems = aOther.m_DefaultFPTextItems;
  759. std::copy( std::begin( aOther.m_LineThickness ), std::end( aOther.m_LineThickness ),
  760. std::begin( m_LineThickness ) );
  761. std::copy( std::begin( aOther.m_TextSize ), std::end( aOther.m_TextSize ),
  762. std::begin( m_TextSize ) );
  763. std::copy( std::begin( aOther.m_TextThickness ), std::end( aOther.m_TextThickness ),
  764. std::begin( m_TextThickness ) );
  765. std::copy( std::begin( aOther.m_TextItalic ), std::end( aOther.m_TextItalic ),
  766. std::begin( m_TextItalic ) );
  767. std::copy( std::begin( aOther.m_TextUpright ), std::end( aOther.m_TextUpright ),
  768. std::begin( m_TextUpright ) );
  769. m_DimensionUnitsMode = aOther.m_DimensionUnitsMode;
  770. m_DimensionPrecision = aOther.m_DimensionPrecision;
  771. m_DimensionUnitsFormat = aOther.m_DimensionUnitsFormat;
  772. m_DimensionSuppressZeroes = aOther.m_DimensionSuppressZeroes;
  773. m_DimensionTextPosition = aOther.m_DimensionTextPosition;
  774. m_DimensionKeepTextAligned = aOther.m_DimensionKeepTextAligned;
  775. m_DimensionArrowLength = aOther.m_DimensionArrowLength;
  776. m_DimensionExtensionOffset = aOther.m_DimensionExtensionOffset;
  777. m_auxOrigin = aOther.m_auxOrigin;
  778. m_gridOrigin = aOther.m_gridOrigin;
  779. m_HasStackup = aOther.m_HasStackup;
  780. m_UseHeightForLengthCalcs= aOther.m_UseHeightForLengthCalcs;
  781. m_trackWidthIndex = aOther.m_trackWidthIndex;
  782. m_viaSizeIndex = aOther.m_viaSizeIndex;
  783. m_diffPairIndex = aOther.m_diffPairIndex;
  784. m_useCustomTrackVia = aOther.m_useCustomTrackVia;
  785. m_customTrackWidth = aOther.m_customTrackWidth;
  786. m_customViaSize = aOther.m_customViaSize;
  787. m_useCustomDiffPair = aOther.m_useCustomDiffPair;
  788. m_customDiffPair = aOther.m_customDiffPair;
  789. m_copperLayerCount = aOther.m_copperLayerCount;
  790. m_enabledLayers = aOther.m_enabledLayers;
  791. m_boardThickness = aOther.m_boardThickness;
  792. m_currentNetClassName = aOther.m_currentNetClassName;
  793. m_stackup = aOther.m_stackup;
  794. m_NetSettings = aOther.m_NetSettings;
  795. m_Pad_Master = std::make_unique<PAD>( *aOther.m_Pad_Master );
  796. m_defaultZoneSettings = aOther.m_defaultZoneSettings;
  797. m_StyleFPFields = aOther.m_StyleFPFields;
  798. m_StyleFPText = aOther.m_StyleFPText;
  799. m_StyleFPShapes = aOther.m_StyleFPShapes;
  800. }
  801. bool BOARD_DESIGN_SETTINGS::operator==( const BOARD_DESIGN_SETTINGS& aOther ) const
  802. {
  803. if( m_TrackWidthList != aOther.m_TrackWidthList ) return false;
  804. if( m_ViasDimensionsList != aOther.m_ViasDimensionsList ) return false;
  805. if( m_DiffPairDimensionsList != aOther.m_DiffPairDimensionsList ) return false;
  806. if( m_CurrentViaType != aOther.m_CurrentViaType ) return false;
  807. if( m_UseConnectedTrackWidth != aOther.m_UseConnectedTrackWidth ) return false;
  808. if( m_TempOverrideTrackWidth != aOther.m_TempOverrideTrackWidth ) return false;
  809. if( m_MinClearance != aOther.m_MinClearance ) return false;
  810. if( m_MinConn != aOther.m_MinConn ) return false;
  811. if( m_TrackMinWidth != aOther.m_TrackMinWidth ) return false;
  812. if( m_ViasMinAnnularWidth != aOther.m_ViasMinAnnularWidth ) return false;
  813. if( m_ViasMinSize != aOther.m_ViasMinSize ) return false;
  814. if( m_MinThroughDrill != aOther.m_MinThroughDrill ) return false;
  815. if( m_MicroViasMinSize != aOther.m_MicroViasMinSize ) return false;
  816. if( m_MicroViasMinDrill != aOther.m_MicroViasMinDrill ) return false;
  817. if( m_CopperEdgeClearance != aOther.m_CopperEdgeClearance ) return false;
  818. if( m_HoleClearance != aOther.m_HoleClearance ) return false;
  819. if( m_HoleToHoleMin != aOther.m_HoleToHoleMin ) return false;
  820. if( m_SilkClearance != aOther.m_SilkClearance ) return false;
  821. if( m_MinResolvedSpokes != aOther.m_MinResolvedSpokes ) return false;
  822. if( m_MinSilkTextHeight != aOther.m_MinSilkTextHeight ) return false;
  823. if( m_MinSilkTextThickness != aOther.m_MinSilkTextThickness ) return false;
  824. if( m_DRCSeverities != aOther.m_DRCSeverities ) return false;
  825. if( m_DrcExclusions != aOther.m_DrcExclusions ) return false;
  826. if( m_DrcExclusionComments != aOther.m_DrcExclusionComments ) return false;
  827. if( m_ZoneKeepExternalFillets != aOther.m_ZoneKeepExternalFillets ) return false;
  828. if( m_MaxError != aOther.m_MaxError ) return false;
  829. if( m_SolderMaskExpansion != aOther.m_SolderMaskExpansion ) return false;
  830. if( m_SolderMaskMinWidth != aOther.m_SolderMaskMinWidth ) return false;
  831. if( m_SolderMaskToCopperClearance != aOther.m_SolderMaskToCopperClearance ) return false;
  832. if( m_SolderPasteMargin != aOther.m_SolderPasteMargin ) return false;
  833. if( m_SolderPasteMarginRatio != aOther.m_SolderPasteMarginRatio ) return false;
  834. if( m_AllowSoldermaskBridgesInFPs != aOther.m_AllowSoldermaskBridgesInFPs ) return false;
  835. if( m_TentViasFront != aOther.m_TentViasFront ) return false;
  836. if( m_TentViasBack != aOther.m_TentViasBack ) return false;
  837. if( m_DefaultFPTextItems != aOther.m_DefaultFPTextItems ) return false;
  838. if( !std::equal( std::begin( m_LineThickness ), std::end( m_LineThickness ),
  839. std::begin( aOther.m_LineThickness ) ) )
  840. return false;
  841. if( !std::equal( std::begin( m_TextSize ), std::end( m_TextSize ),
  842. std::begin( aOther.m_TextSize ) ) )
  843. return false;
  844. if( !std::equal( std::begin( m_TextThickness ), std::end( m_TextThickness ),
  845. std::begin( aOther.m_TextThickness ) ) )
  846. return false;
  847. if( !std::equal( std::begin( m_TextItalic ), std::end( m_TextItalic ),
  848. std::begin( aOther.m_TextItalic ) ) )
  849. return false;
  850. if( !std::equal( std::begin( m_TextUpright ), std::end( m_TextUpright ),
  851. std::begin( aOther.m_TextUpright ) ) )
  852. return false;
  853. if( m_DimensionUnitsMode != aOther.m_DimensionUnitsMode ) return false;
  854. if( m_DimensionPrecision != aOther.m_DimensionPrecision ) return false;
  855. if( m_DimensionUnitsFormat != aOther.m_DimensionUnitsFormat ) return false;
  856. if( m_DimensionSuppressZeroes != aOther.m_DimensionSuppressZeroes ) return false;
  857. if( m_DimensionTextPosition != aOther.m_DimensionTextPosition ) return false;
  858. if( m_DimensionKeepTextAligned != aOther.m_DimensionKeepTextAligned ) return false;
  859. if( m_DimensionArrowLength != aOther.m_DimensionArrowLength ) return false;
  860. if( m_DimensionExtensionOffset != aOther.m_DimensionExtensionOffset ) return false;
  861. if( m_auxOrigin != aOther.m_auxOrigin ) return false;
  862. if( m_gridOrigin != aOther.m_gridOrigin ) return false;
  863. if( m_HasStackup != aOther.m_HasStackup ) return false;
  864. if( m_UseHeightForLengthCalcs != aOther.m_UseHeightForLengthCalcs ) return false;
  865. if( m_trackWidthIndex != aOther.m_trackWidthIndex ) return false;
  866. if( m_viaSizeIndex != aOther.m_viaSizeIndex ) return false;
  867. if( m_diffPairIndex != aOther.m_diffPairIndex ) return false;
  868. if( m_useCustomTrackVia != aOther.m_useCustomTrackVia ) return false;
  869. if( m_customTrackWidth != aOther.m_customTrackWidth ) return false;
  870. if( m_customViaSize != aOther.m_customViaSize ) return false;
  871. if( m_useCustomDiffPair != aOther.m_useCustomDiffPair ) return false;
  872. if( m_customDiffPair != aOther.m_customDiffPair ) return false;
  873. if( m_copperLayerCount != aOther.m_copperLayerCount ) return false;
  874. if( m_enabledLayers != aOther.m_enabledLayers ) return false;
  875. if( m_boardThickness != aOther.m_boardThickness ) return false;
  876. if( m_currentNetClassName != aOther.m_currentNetClassName ) return false;
  877. if( m_stackup != aOther.m_stackup ) return false;
  878. if( *m_NetSettings != *aOther.m_NetSettings ) return false;
  879. if( *m_Pad_Master != *aOther.m_Pad_Master ) return false;
  880. if( m_defaultZoneSettings != aOther.m_defaultZoneSettings ) return false;
  881. if( m_StyleFPFields != aOther.m_StyleFPFields ) return false;
  882. if( m_StyleFPText != aOther.m_StyleFPText ) return false;
  883. if( m_StyleFPShapes != aOther.m_StyleFPShapes ) return false;
  884. return true;
  885. }
  886. bool BOARD_DESIGN_SETTINGS::migrateSchema0to1()
  887. {
  888. /**
  889. * Schema 0 to 1: default dimension precision changed in meaning.
  890. * Previously it was an enum with the following meaning:
  891. *
  892. * 0: 0.01mm / 1 mil / 0.001 in
  893. * 1: 0.001mm / 0.1 mil / 0.0001 in
  894. * 2: 0.0001mm / 0.01 mil / 0.00001 in
  895. *
  896. * Now it is independent of display units and is an integer meaning the number of digits
  897. * displayed after the decimal point, so we have to migrate based on the default units.
  898. *
  899. * The units is an integer with the following mapping:
  900. *
  901. * 0: Inches
  902. * 1: Mils
  903. * 2: Millimeters
  904. */
  905. std::string units_ptr( "defaults.dimension_units" );
  906. std::string precision_ptr( "defaults.dimension_precision" );
  907. if( !( Contains( units_ptr ) && Contains( precision_ptr ) &&
  908. At( units_ptr ).is_number_integer() &&
  909. At( precision_ptr ).is_number_integer() ) )
  910. {
  911. // if either is missing or invalid, migration doesn't make sense
  912. return true;
  913. }
  914. int units = *Get<int>( units_ptr );
  915. int precision = *Get<int>( precision_ptr );
  916. // The enum maps directly to precision if the units is mils
  917. int extraDigits = 0;
  918. switch( units )
  919. {
  920. case 0: extraDigits = 3; break;
  921. case 2: extraDigits = 2; break;
  922. default: break;
  923. }
  924. precision += extraDigits;
  925. Set( precision_ptr, precision );
  926. return true;
  927. }
  928. bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
  929. {
  930. bool ret = NESTED_SETTINGS::LoadFromFile( aDirectory );
  931. // A number of things won't have been translated by the PROJECT_FILE migration because of
  932. // descoped objects required to decode this data. So, it will be in the legacy.pcbnew
  933. // section and needs to be pulled out here
  934. PROJECT_FILE* project = dynamic_cast<PROJECT_FILE*>( GetParent() );
  935. if( !project )
  936. return ret;
  937. bool migrated = false;
  938. auto drcName =
  939. []( int aCode ) -> std::string
  940. {
  941. std::shared_ptr<DRC_ITEM> item = DRC_ITEM::Create( aCode );
  942. wxString name = item->GetSettingsKey();
  943. return std::string( name.ToUTF8() );
  944. };
  945. const std::string rs = "rule_severities.";
  946. const std::string no_courtyard_key = "legacy_no_courtyard_defined";
  947. const std::string courtyard_overlap_key = "legacy_courtyards_overlap";
  948. try
  949. {
  950. nlohmann::json& severities =
  951. project->Internals()->at( "/board/design_settings/rule_severities"_json_pointer );
  952. if( severities.contains( no_courtyard_key ) )
  953. {
  954. if( severities[no_courtyard_key].get<bool>() )
  955. Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
  956. else
  957. Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
  958. severities.erase( no_courtyard_key );
  959. migrated = true;
  960. }
  961. if( severities.contains( courtyard_overlap_key ) )
  962. {
  963. if( severities[courtyard_overlap_key].get<bool>() )
  964. Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
  965. else
  966. Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
  967. severities.erase( courtyard_overlap_key );
  968. migrated = true;
  969. }
  970. }
  971. catch( ... )
  972. {
  973. }
  974. if( Contains( "legacy" ) )
  975. {
  976. // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
  977. // so we do the same for legacy boards.
  978. m_ZoneKeepExternalFillets = true;
  979. project->At( "legacy" ).erase( "pcbnew" );
  980. }
  981. // Now that we have everything, we need to load again
  982. if( migrated )
  983. Load();
  984. return ret;
  985. }
  986. SEVERITY BOARD_DESIGN_SETTINGS::GetSeverity( int aDRCErrorCode )
  987. {
  988. return m_DRCSeverities[ aDRCErrorCode ];
  989. }
  990. bool BOARD_DESIGN_SETTINGS::Ignore( int aDRCErrorCode )
  991. {
  992. return m_DRCSeverities[ aDRCErrorCode ] == RPT_SEVERITY_IGNORE;
  993. }
  994. int BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue() const
  995. {
  996. int biggest = std::max( m_MinClearance, m_HoleClearance );
  997. DRC_CONSTRAINT constraint;
  998. biggest = std::max( biggest, m_HoleToHoleMin );
  999. biggest = std::max( biggest, m_CopperEdgeClearance );
  1000. if( m_DRCEngine )
  1001. {
  1002. m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
  1003. biggest = std::max( biggest, constraint.Value().Min() );
  1004. m_DRCEngine->QueryWorstConstraint( PHYSICAL_CLEARANCE_CONSTRAINT, constraint );
  1005. biggest = std::max( biggest, constraint.Value().Min() );
  1006. m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
  1007. biggest = std::max( biggest, constraint.Value().Min() );
  1008. m_DRCEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, constraint );
  1009. biggest = std::max( biggest, constraint.Value().Min() );
  1010. m_DRCEngine->QueryWorstConstraint( HOLE_TO_HOLE_CONSTRAINT, constraint );
  1011. biggest = std::max( biggest, constraint.Value().Min() );
  1012. }
  1013. return biggest;
  1014. }
  1015. int BOARD_DESIGN_SETTINGS::GetSmallestClearanceValue() const
  1016. {
  1017. int clearance = m_NetSettings->m_DefaultNetClass->GetClearance();
  1018. for( const auto& [ name, netclass ] : m_NetSettings->m_NetClasses )
  1019. clearance = std::min( clearance, netclass->GetClearance() );
  1020. return clearance;
  1021. }
  1022. void BOARD_DESIGN_SETTINGS::SetViaSizeIndex( unsigned aIndex )
  1023. {
  1024. m_viaSizeIndex = std::min( aIndex, (unsigned) m_ViasDimensionsList.size() );
  1025. m_useCustomTrackVia = false;
  1026. }
  1027. int BOARD_DESIGN_SETTINGS::GetCurrentViaSize() const
  1028. {
  1029. if( m_useCustomTrackVia )
  1030. return m_customViaSize.m_Diameter;
  1031. else if( m_viaSizeIndex == 0 )
  1032. return m_NetSettings->m_DefaultNetClass->GetViaDiameter();
  1033. else
  1034. return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter;
  1035. }
  1036. int BOARD_DESIGN_SETTINGS::GetCurrentViaDrill() const
  1037. {
  1038. int drill;
  1039. if( m_useCustomTrackVia )
  1040. drill = m_customViaSize.m_Drill;
  1041. else if( m_viaSizeIndex == 0 )
  1042. drill = m_NetSettings->m_DefaultNetClass->GetViaDrill();
  1043. else
  1044. drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill;
  1045. return drill > 0 ? drill : -1;
  1046. }
  1047. void BOARD_DESIGN_SETTINGS::SetTrackWidthIndex( unsigned aIndex )
  1048. {
  1049. m_trackWidthIndex = std::min( aIndex, (unsigned) m_TrackWidthList.size() );
  1050. m_useCustomTrackVia = false;
  1051. }
  1052. int BOARD_DESIGN_SETTINGS::GetCurrentTrackWidth() const
  1053. {
  1054. if( m_useCustomTrackVia )
  1055. return m_customTrackWidth;
  1056. else if( m_trackWidthIndex == 0 )
  1057. return m_NetSettings->m_DefaultNetClass->GetTrackWidth();
  1058. else
  1059. return m_TrackWidthList[ m_trackWidthIndex ];
  1060. }
  1061. void BOARD_DESIGN_SETTINGS::SetDiffPairIndex( unsigned aIndex )
  1062. {
  1063. if( !m_DiffPairDimensionsList.empty() )
  1064. {
  1065. m_diffPairIndex = std::min( aIndex,
  1066. static_cast<unsigned>( m_DiffPairDimensionsList.size() ) - 1 );
  1067. }
  1068. m_useCustomDiffPair = false;
  1069. }
  1070. int BOARD_DESIGN_SETTINGS::GetCurrentDiffPairWidth() const
  1071. {
  1072. if( m_useCustomDiffPair )
  1073. {
  1074. return m_customDiffPair.m_Width;
  1075. }
  1076. else if( m_diffPairIndex == 0 )
  1077. {
  1078. if( m_NetSettings->m_DefaultNetClass->HasDiffPairWidth() )
  1079. return m_NetSettings->m_DefaultNetClass->GetDiffPairWidth();
  1080. else
  1081. return m_NetSettings->m_DefaultNetClass->GetTrackWidth();
  1082. }
  1083. else
  1084. {
  1085. return m_DiffPairDimensionsList[m_diffPairIndex].m_Width;
  1086. }
  1087. }
  1088. int BOARD_DESIGN_SETTINGS::GetCurrentDiffPairGap() const
  1089. {
  1090. if( m_useCustomDiffPair )
  1091. {
  1092. return m_customDiffPair.m_Gap;
  1093. }
  1094. else if( m_diffPairIndex == 0 )
  1095. {
  1096. if( m_NetSettings->m_DefaultNetClass->HasDiffPairGap() )
  1097. return m_NetSettings->m_DefaultNetClass->GetDiffPairGap();
  1098. else
  1099. return m_NetSettings->m_DefaultNetClass->GetClearance();
  1100. }
  1101. else
  1102. {
  1103. return m_DiffPairDimensionsList[m_diffPairIndex].m_Gap;
  1104. }
  1105. }
  1106. int BOARD_DESIGN_SETTINGS::GetCurrentDiffPairViaGap() const
  1107. {
  1108. if( m_useCustomDiffPair )
  1109. {
  1110. return m_customDiffPair.m_ViaGap;
  1111. }
  1112. else if( m_diffPairIndex == 0 )
  1113. {
  1114. if( m_NetSettings->m_DefaultNetClass->HasDiffPairViaGap() )
  1115. return m_NetSettings->m_DefaultNetClass->GetDiffPairViaGap();
  1116. else
  1117. return GetCurrentDiffPairGap();
  1118. }
  1119. else
  1120. {
  1121. return m_DiffPairDimensionsList[m_diffPairIndex].m_ViaGap;
  1122. }
  1123. }
  1124. void BOARD_DESIGN_SETTINGS::SetCopperLayerCount( int aNewLayerCount )
  1125. {
  1126. m_copperLayerCount = aNewLayerCount;
  1127. // Update only enabled copper layers mask
  1128. m_enabledLayers &= ~LSET::AllCuMask();
  1129. if( aNewLayerCount > 0 )
  1130. m_enabledLayers |= LSET::AllCuMask( aNewLayerCount );
  1131. }
  1132. void BOARD_DESIGN_SETTINGS::SetEnabledLayers( LSET aMask )
  1133. {
  1134. // Back and front layers are always enabled.
  1135. aMask.set( B_Cu ).set( F_Cu );
  1136. m_enabledLayers = aMask;
  1137. // update m_CopperLayerCount to ensure its consistency with m_EnabledLayers
  1138. m_copperLayerCount = ( aMask & LSET::AllCuMask() ).count();
  1139. }
  1140. // Return the layer class index { silk, copper, edges & courtyards, fab, others } of the
  1141. // given layer.
  1142. int BOARD_DESIGN_SETTINGS::GetLayerClass( PCB_LAYER_ID aLayer ) const
  1143. {
  1144. if( aLayer == F_SilkS || aLayer == B_SilkS )
  1145. return LAYER_CLASS_SILK;
  1146. else if( IsCopperLayer( aLayer ) )
  1147. return LAYER_CLASS_COPPER;
  1148. else if( aLayer == Edge_Cuts )
  1149. return LAYER_CLASS_EDGES;
  1150. else if( aLayer == F_CrtYd || aLayer == B_CrtYd )
  1151. return LAYER_CLASS_COURTYARD;
  1152. else if( aLayer == F_Fab || aLayer == B_Fab )
  1153. return LAYER_CLASS_FAB;
  1154. else
  1155. return LAYER_CLASS_OTHERS;
  1156. }
  1157. int BOARD_DESIGN_SETTINGS::GetDRCEpsilon() const
  1158. {
  1159. return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
  1160. }
  1161. int BOARD_DESIGN_SETTINGS::GetHolePlatingThickness() const
  1162. {
  1163. return pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
  1164. }
  1165. int BOARD_DESIGN_SETTINGS::GetLineThickness( PCB_LAYER_ID aLayer ) const
  1166. {
  1167. return m_LineThickness[ GetLayerClass( aLayer ) ];
  1168. }
  1169. VECTOR2I BOARD_DESIGN_SETTINGS::GetTextSize( PCB_LAYER_ID aLayer ) const
  1170. {
  1171. return m_TextSize[ GetLayerClass( aLayer ) ];
  1172. }
  1173. int BOARD_DESIGN_SETTINGS::GetTextThickness( PCB_LAYER_ID aLayer ) const
  1174. {
  1175. return m_TextThickness[ GetLayerClass( aLayer ) ];
  1176. }
  1177. bool BOARD_DESIGN_SETTINGS::GetTextItalic( PCB_LAYER_ID aLayer ) const
  1178. {
  1179. return m_TextItalic[ GetLayerClass( aLayer ) ];
  1180. }
  1181. bool BOARD_DESIGN_SETTINGS::GetTextUpright( PCB_LAYER_ID aLayer ) const
  1182. {
  1183. return m_TextUpright[ GetLayerClass( aLayer ) ];
  1184. }
  1185. void BOARD_DESIGN_SETTINGS::SetDefaultMasterPad()
  1186. {
  1187. m_Pad_Master.get()->SetSizeX( pcbIUScale.mmToIU( DEFAULT_PAD_WIDTH_MM ) );
  1188. m_Pad_Master.get()->SetSizeY( pcbIUScale.mmToIU( DEFAULT_PAD_HEIGTH_MM ) );
  1189. m_Pad_Master.get()->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
  1190. m_Pad_Master.get()->SetDrillSize(
  1191. VECTOR2I( pcbIUScale.mmToIU( DEFAULT_PAD_DRILL_DIAMETER_MM ), 0 ) );
  1192. m_Pad_Master.get()->SetShape( PAD_SHAPE::ROUNDRECT );
  1193. m_Pad_Master.get()->SetRoundRectCornerRadius(
  1194. pcbIUScale.mmToIU( DEFAULT_PAD_HEIGTH_MM / 100.0 * DEFAULT_PAD_REACT_RADIUS ) );
  1195. }