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