KiCad PCB EDA Suite
board_design_settings.cpp
Go to the documentation of this file.
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>
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 
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.
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
65 
66  // if true, when creating a new track starting on an existing track, use this track width
68 
70  m_MicroViasAllowed = false;
71 
72  // First is always the reference designator
73  m_DefaultFPTextItems.emplace_back( wxT( "REF**" ), true, F_SilkS );
74  // Second is always the value
75  m_DefaultFPTextItems.emplace_back( wxT( "" ), true, F_Fab );
76  // Any following ones are freebies
77  m_DefaultFPTextItems.emplace_back( wxT( "${REF}" ), true, F_Fab );
78 
83  m_TextItalic[ LAYER_CLASS_SILK ] = false;
85 
92 
93  // Edges & Courtyards; text properties aren't used but better to have them holding
94  // reasonable values than not.
100  m_TextUpright[ LAYER_CLASS_EDGES ] = false;
101 
108 
113  m_TextItalic[ LAYER_CLASS_FAB ] = false;
114  m_TextUpright[ LAYER_CLASS_FAB ] = false;
115 
120  m_TextItalic[ LAYER_CLASS_OTHERS ] = false;
122 
131 
132  m_useCustomTrackVia = false;
136 
137  m_useCustomDiffPair = false;
141 
153 
154  for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode )
155  m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
156 
158 
162 
165 
170 
173 
174  m_MaxError = ARC_HIGH_DEF;
175  m_ZoneFillVersion = 6; // Use new algo by default to fill zones
176  m_ZoneKeepExternalFillets = false; // Use new algo by default. Legacy boards might
177  // want to set it to true for old algo....
179 
180  // Global mask margins:
183 
184  // Solder paste margin absolute value
186  // Solder paste margin as a ratio of pad size
187  // The final margin is the sum of these 2 values
188  // Usually < 0 because the mask is smaller than pad
190 
191  // Layer thickness for 3D viewer
193 
194  m_viaSizeIndex = 0;
195  m_trackWidthIndex = 0;
196  m_diffPairIndex = 0;
197 
198  // Parameters stored in JSON in the project file
199 
200  // NOTE: Previously, BOARD_DESIGN_SETTINGS stored the basic board layer information (layer
201  // names and enable/disable state) in the project file even though this information is also
202  // stored in the board file. This was implemented for importing these settings from another
203  // project. Going forward, the import feature will just import from other board files (since
204  // we could have multi-board projects in the future anyway) so this functionality is dropped.
205 
206  m_params.emplace_back( new PARAM<bool>( "rules.allow_microvias", &m_MicroViasAllowed, false ) );
207 
208  m_params.emplace_back( new PARAM<bool>( "rules.allow_blind_buried_vias",
209  &m_BlindBuriedViaAllowed, false ) );
210 
211  m_params.emplace_back( new PARAM<bool>( "rules.use_height_for_length_calcs",
212  &m_UseHeightForLengthCalcs, true ) );
213 
214  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_clearance", &m_MinClearance,
216  MM_PER_IU ) );
217 
218  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_track_width", &m_TrackMinWidth,
220  MM_PER_IU ) );
221 
222  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_annular_width",
224  Millimeter2iu( 25.0 ), MM_PER_IU ) );
225 
226  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_diameter", &m_ViasMinSize,
228  MM_PER_IU ) );
229 
230  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_through_hole_diameter",
232  Millimeter2iu( 25.0 ), MM_PER_IU ) );
233 
234  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_diameter",
236  Millimeter2iu( 10.0 ), MM_PER_IU ) );
237 
238  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_drill", &m_MicroViasMinDrill,
240  Millimeter2iu( 10.0 ), MM_PER_IU ) );
241 
242  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_to_hole", &m_HoleToHoleMin,
244  MM_PER_IU ) );
245 
246  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_clearance", &m_HoleClearance,
248  MM_PER_IU ) );
249 
250  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_silk_clearance", &m_SilkClearance,
252  MM_PER_IU ) );
253 
254  // Note: a clearance of -0.01 is a flag indicating we should use the legacy (pre-6.0) method
255  // based on the edge cut thicknesses.
256  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_copper_edge_clearance",
258  Millimeter2iu( -0.01 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
259 
260  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
261  [&]() -> nlohmann::json
262  {
263  nlohmann::json ret = {};
264 
265  for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
266  {
267  wxString name = item.GetSettingsKey();
268  int code = item.GetErrorCode();
269 
270  if( name.IsEmpty() || m_DRCSeverities.count( code ) == 0 )
271  continue;
272 
273  ret[std::string( name.ToUTF8() )] = SeverityToString( m_DRCSeverities[code] );
274  }
275 
276  return ret;
277  },
278  [&]( const nlohmann::json& aJson )
279  {
280  if( !aJson.is_object() )
281  return;
282 
283  for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
284  {
285  wxString name = item.GetSettingsKey();
286  std::string key( name.ToUTF8() );
287 
288  if( aJson.contains( key ) )
289  m_DRCSeverities[item.GetErrorCode()] = SeverityFromString( aJson[key] );
290  }
291  }, {} ) );
292 
293  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "drc_exclusions",
294  [&]() -> nlohmann::json
295  {
296  nlohmann::json js = nlohmann::json::array();
297 
298  for( const auto& entry : m_DrcExclusions )
299  js.push_back( entry );
300 
301  return js;
302  },
303  [&]( const nlohmann::json& aObj )
304  {
305  m_DrcExclusions.clear();
306 
307  if( !aObj.is_array() )
308  return;
309 
310  for( const nlohmann::json& entry : aObj )
311  {
312  if( entry.empty() )
313  continue;
314 
315  m_DrcExclusions.insert( entry.get<wxString>() );
316  }
317  },
318  {} ) );
319 
320  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "track_widths",
321  [&]() -> nlohmann::json
322  {
323  nlohmann::json js = nlohmann::json::array();
324 
325  for( const int& width : m_TrackWidthList )
326  js.push_back( Iu2Millimeter( width ) );
327 
328  return js;
329  },
330  [&]( const nlohmann::json& aJson )
331  {
332  if( !aJson.is_array() )
333  return;
334 
335  m_TrackWidthList.clear();
336 
337  for( const nlohmann::json& entry : aJson )
338  {
339  if( entry.empty() )
340  continue;
341 
342  m_TrackWidthList.emplace_back( Millimeter2iu( entry.get<double>() ) );
343  }
344  },
345  {} ) );
346 
347  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "via_dimensions",
348  [&]() -> nlohmann::json
349  {
350  nlohmann::json js = nlohmann::json::array();
351 
352  for( const auto& via : m_ViasDimensionsList )
353  {
354  nlohmann::json entry = {};
355 
356  entry["diameter"] = Iu2Millimeter( via.m_Diameter );
357  entry["drill"] = Iu2Millimeter( via.m_Drill );
358 
359  js.push_back( entry );
360  }
361 
362  return js;
363  },
364  [&]( const nlohmann::json& aObj )
365  {
366  if( !aObj.is_array() )
367  return;
368 
369  m_ViasDimensionsList.clear();
370 
371  for( const nlohmann::json& entry : aObj )
372  {
373  if( entry.empty() || !entry.is_object() )
374  continue;
375 
376  if( !entry.contains( "diameter" ) || !entry.contains( "drill" ) )
377  continue;
378 
379  int diameter = Millimeter2iu( entry["diameter"].get<double>() );
380  int drill = Millimeter2iu( entry["drill"].get<double>() );
381 
382  m_ViasDimensionsList.emplace_back( VIA_DIMENSION( diameter, drill ) );
383  }
384  },
385  {} ) );
386 
387  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "diff_pair_dimensions",
388  [&]() -> nlohmann::json
389  {
390  nlohmann::json js = nlohmann::json::array();
391 
392  for( const auto& pair : m_DiffPairDimensionsList )
393  {
394  nlohmann::json entry = {};
395 
396  entry["width"] = Iu2Millimeter( pair.m_Width );
397  entry["gap"] = Iu2Millimeter( pair.m_Gap );
398  entry["via_gap"] = Iu2Millimeter( pair.m_ViaGap );
399 
400  js.push_back( entry );
401  }
402 
403  return js;
404  },
405  [&]( const nlohmann::json& aObj )
406  {
407  if( !aObj.is_array() )
408  return;
409 
410  m_DiffPairDimensionsList.clear();
411 
412  for( const nlohmann::json& entry : aObj )
413  {
414  if( entry.empty() || !entry.is_object() )
415  continue;
416 
417  if( !entry.contains( "width" ) || !entry.contains( "gap" )
418  || !entry.contains( "via_gap" ) )
419  continue;
420 
421  int width = Millimeter2iu( entry["width"].get<double>() );
422  int gap = Millimeter2iu( entry["gap"].get<double>() );
423  int via_gap = Millimeter2iu( entry["via_gap"].get<double>() );
424 
425  m_DiffPairDimensionsList.emplace_back(
426  DIFF_PAIR_DIMENSION( width, gap, via_gap ) );
427  }
428  },
429  {} ) );
430 
431  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_line_width",
433  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
434 
435  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_v",
437  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
438 
439  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_h",
441  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
442 
443  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_thickness",
445  TEXTS_MAX_WIDTH, MM_PER_IU ) );
446 
447  m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_italic",
448  &m_TextItalic[LAYER_CLASS_SILK], false ) );
449 
450  m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_upright",
451  &m_TextUpright[ LAYER_CLASS_SILK ], true ) );
452 
453  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_line_width",
455  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
456 
457  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_v",
459  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
460 
461  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_h",
463  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
464 
465  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_thickness",
467  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
468 
469  m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_italic",
470  &m_TextItalic[LAYER_CLASS_COPPER], false ) );
471 
472  m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_upright",
473  &m_TextUpright[LAYER_CLASS_COPPER], true ) );
474 
475  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.board_outline_line_width",
477  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
478 
479  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.courtyard_line_width",
481  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
482 
483  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_line_width",
485  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
486 
487  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_v",
489  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
490 
491  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_h",
493  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
494 
495  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_thickness",
497  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
498 
499  m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_italic",
500  &m_TextItalic[LAYER_CLASS_FAB], false ) );
501 
502  m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_upright",
503  &m_TextUpright[LAYER_CLASS_FAB], true ) );
504 
505  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_line_width",
507  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
508 
509  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_v",
511  TEXTS_MAX_SIZE, MM_PER_IU ) );
512 
513  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_h",
515  TEXTS_MAX_SIZE, MM_PER_IU ) );
516 
517  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_thickness",
519  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
520 
521  m_params.emplace_back( new PARAM<bool>( "defaults.other_text_italic",
522  &m_TextItalic[LAYER_CLASS_OTHERS], false ) );
523 
524  m_params.emplace_back( new PARAM<bool>( "defaults.other_text_upright",
525  &m_TextUpright[LAYER_CLASS_OTHERS], true ) );
526 
527  m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_MODE>( "defaults.dimension_units",
530 
531  m_params.emplace_back( new PARAM<int>( "defaults.dimension_precision",
532  &m_DimensionPrecision, 4, 0, 5 ) );
533 
534  m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_FORMAT>( "defaults.dimensions.units_format",
537 
538  m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.suppress_zeroes",
539  &m_DimensionSuppressZeroes, false ) );
540 
541  // NOTE: excluding DIM_TEXT_POSITION::MANUAL from the valid range here
542  m_params.emplace_back( new PARAM_ENUM<DIM_TEXT_POSITION>( "defaults.dimensions.text_position",
545 
546  m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.keep_text_aligned",
547  &m_DimensionKeepTextAligned, true ) );
548 
549  m_params.emplace_back( new PARAM<int>( "defaults.dimensions.arrow_length",
551  Mils2iu( DEFAULT_DIMENSION_ARROW_LENGTH ) ) );
552 
553  m_params.emplace_back( new PARAM<int>( "defaults.dimensions.extension_offset",
556 
557  m_params.emplace_back( new PARAM<bool>( "defaults.zones.45_degree_only",
559 
560  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.zones.min_clearance",
562  Millimeter2iu( 0.0 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
563 
564  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "defaults.pads",
565  [&]() -> nlohmann::json
566  {
567  nlohmann::json ret =
568  {
569  { "width", Iu2Millimeter( m_Pad_Master->GetSize().x ) },
570  { "height", Iu2Millimeter( m_Pad_Master->GetSize().y ) },
571  { "drill", Iu2Millimeter( m_Pad_Master->GetDrillSize().x ) }
572  };
573 
574  return ret;
575  },
576  [&]( const nlohmann::json& aJson )
577  {
578  if( aJson.contains( "width" ) && aJson.contains( "height" )
579  && aJson.contains( "drill" ) )
580  {
581  wxSize sz;
582  sz.SetWidth( Millimeter2iu( aJson["width"].get<double>() ) );
583  sz.SetHeight( Millimeter2iu( aJson["height"].get<double>() ) );
584 
585  m_Pad_Master->SetSize( sz );
586 
587  int drill = Millimeter2iu( aJson["drill"].get<double>() );
588 
589  m_Pad_Master->SetDrillSize( wxSize( drill, drill ) );
590  }
591  }, {} ) );
592 
593  m_params.emplace_back( new PARAM_SCALED<int>( "rules.max_error", &m_MaxError, ARC_HIGH_DEF,
594  Millimeter2iu( 0.0001 ), Millimeter2iu( 1.0 ), MM_PER_IU ) );
595 
596  // TODO: replace with zones_fill_version parameter and migrate zones_use_no_outline?
597  m_params.emplace_back( new PARAM_LAMBDA<bool>( "zones_use_no_outline",
598  [this]() -> bool
599  {
600  return m_ZoneFillVersion >= 6;
601  },
602  [this]( bool aVal )
603  {
604  m_ZoneFillVersion = aVal ? 6 : 5;
605  },
606  true ) );
607 
608  m_params.emplace_back( new PARAM<bool>( "zones_allow_external_fillets",
609  &m_ZoneKeepExternalFillets, false ) );
610 
611  registerMigration( 0, 1, std::bind( &BOARD_DESIGN_SETTINGS::migrateSchema0to1, this ) );
612 
613  registerMigration( 1, 2,
614  [&]() -> bool
615  {
616  // Schema 1 to 2: move mask and paste margin settings back to board.
617  // The parameters are removed, so we just have to manually load them here and
618  // they will get saved with the board
619  if( OPT<double> optval = Get<double>( "rules.solder_mask_clearance" ) )
620  m_SolderMaskMargin = static_cast<int>( *optval * IU_PER_MM );
621 
622  if( OPT<double> optval = Get<double>( "rules.solder_mask_min_width" ) )
623  m_SolderMaskMinWidth = static_cast<int>( *optval * IU_PER_MM );
624 
625  if( OPT<double> optval = Get<double>( "rules.solder_paste_clearance" ) )
626  m_SolderPasteMargin = static_cast<int>( *optval * IU_PER_MM );
627 
628  if( OPT<double> optval = Get<double>( "rules.solder_paste_margin_ratio" ) )
629  m_SolderPasteMarginRatio = *optval;
630 
631  try
632  {
633  At( "rules" ).erase( "solder_mask_clearance" );
634  At( "rules" ).erase( "solder_mask_min_width" );
635  At( "rules" ).erase( "solder_paste_clearance" );
636  At( "rules" ).erase( "solder_paste_margin_ratio" );
637  }
638  catch( ... )
639  {}
640 
641  return true;
642  } );
643 }
644 
645 
647 {
648  if( m_parent )
649  {
651  m_parent = nullptr;
652  }
653 }
654 
655 
657  NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aOther.m_parent,
658  aOther.m_path ),
659  m_Pad_Master( nullptr )
660 {
661  initFromOther( aOther );
662 }
663 
664 
666 {
667  initFromOther( aOther );
668  return *this;
669 }
670 
671 
673 {
674  // Copy of NESTED_SETTINGS around is not allowed, so let's just update the params.
685  m_ViasMinSize = aOther.m_ViasMinSize;
697  m_MaxError = aOther.m_MaxError;
703 
704  std::copy( std::begin( aOther.m_LineThickness ), std::end( aOther.m_LineThickness ),
705  std::begin( m_LineThickness ) );
706 
707  std::copy( std::begin( aOther.m_TextSize ), std::end( aOther.m_TextSize ),
708  std::begin( m_TextSize ) );
709 
710  std::copy( std::begin( aOther.m_TextThickness ), std::end( aOther.m_TextThickness ),
711  std::begin( m_TextThickness ) );
712 
713  std::copy( std::begin( aOther.m_TextItalic ), std::end( aOther.m_TextItalic ),
714  std::begin( m_TextItalic ) );
715 
716  std::copy( std::begin( aOther.m_TextUpright ), std::end( aOther.m_TextUpright ),
717  std::begin( m_TextUpright ) );
718 
727 
728  m_AuxOrigin = aOther.m_AuxOrigin;
729  m_GridOrigin = aOther.m_GridOrigin;
730  m_HasStackup = aOther.m_HasStackup;
732 
745  m_stackup = aOther.m_stackup;
746 
747  // Only take the pointer from the other if it isn't the default
748  if( aOther.m_netClasses == &aOther.m_internalNetClasses )
750  else
751  m_netClasses = aOther.m_netClasses;
752 
754 }
755 
756 
758 {
776  std::string units_ptr( "defaults.dimension_units" );
777  std::string precision_ptr( "defaults.dimension_precision" );
778 
779  if( !( Contains( units_ptr ) && Contains( precision_ptr ) &&
780  At( units_ptr ).is_number_integer() &&
781  At( precision_ptr ).is_number_integer() ) )
782  {
783  // if either is missing or invalid, migration doesn't make sense
784  return true;
785  }
786 
787  int units = Get<int>( units_ptr ).value();
788  int precision = Get<int>( precision_ptr ).value();
789 
790  // The enum maps directly to precision if the units is mils
791  int extraDigits = 0;
792 
793  switch( units )
794  {
795  case 0: extraDigits = 3; break;
796  case 2: extraDigits = 2; break;
797  default: break;
798  }
799 
800  precision += extraDigits;
801 
802  Set( precision_ptr, precision );
803 
804  return true;
805 }
806 
807 
808 bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
809 {
810  bool ret = NESTED_SETTINGS::LoadFromFile( aDirectory );
811 
812  // A number of things won't have been translated by the PROJECT_FILE migration because of
813  // descoped objects required to decode this data. So, it will be in the legacy.pcbnew
814  // section and needs to be pulled out here
815 
816  PROJECT_FILE* project = dynamic_cast<PROJECT_FILE*>( GetParent() );
817 
818  if( !project )
819  return ret;
820 
821  bool migrated = false;
822 
823  auto drcName =
824  []( int aCode ) -> std::string
825  {
826  std::shared_ptr<DRC_ITEM> item = DRC_ITEM::Create( aCode );
827  wxString name = item->GetSettingsKey();
828  return std::string( name.ToUTF8() );
829  };
830 
831  std::string bp = "board.design_settings.rule_severities.";
832  std::string rs = "rule_severities.";
833 
834  if( OPT<bool> v = project->Get<bool>( bp + "legacy_no_courtyard_defined" ) )
835  {
836  if( *v )
837  Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
838  else
839  Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
840 
841  project->Internals()->erase( m_internals->PointerFromString( bp + "legacy_no_courtyard_defined" ) );
842  migrated = true;
843  }
844 
845  if( OPT<bool> v = project->Get<bool>( bp + "legacy_courtyards_overlap" ) )
846  {
847  if( *v )
848  Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
849  else
850  Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
851 
852  project->Internals()->erase( JSON_SETTINGS_INTERNALS::PointerFromString( bp + "legacy_courtyards_overlap" ) );
853  migrated = true;
854  }
855 
856  if( Contains( "legacy" ) )
857  {
858  // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
859  // so we do the same for legacy boards.
861 
862  project->At( "legacy" ).erase( "pcbnew" );
863  }
864 
865  // Now that we have everything, we need to load again
866  if( migrated )
867  Load();
868 
869  return ret;
870 }
871 
872 
874 {
875  return m_DRCSeverities[ aDRCErrorCode ];
876 }
877 
878 
879 bool BOARD_DESIGN_SETTINGS::Ignore( int aDRCErrorCode )
880 {
881  return m_DRCSeverities[ aDRCErrorCode ] == RPT_SEVERITY_IGNORE;
882 }
883 
884 
886 {
887  int biggest = 0;
888  DRC_CONSTRAINT constraint;
889 
890  if( m_DRCEngine )
891  {
892  m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
893  biggest = std::max( biggest, constraint.Value().Min() );
894 
895  m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
896  biggest = std::max( biggest, constraint.Value().Min() );
897 
898  m_DRCEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, constraint );
899  biggest = std::max( biggest, constraint.Value().Min() );
900  }
901 
902  return biggest;
903 }
904 
905 
907 {
908  int clearance = GetDefault()->GetClearance();
909 
910  for( const std::pair<const wxString, NETCLASSPTR>& netclass : GetNetClasses().NetClasses() )
911  clearance = std::min( clearance, netclass.second->GetClearance() );
912 
913  return clearance;
914 }
915 
916 
918 {
919  NETCLASSPTR netclass = GetNetClasses().Find( m_currentNetClassName );
920 
921  return netclass->GetuViaDiameter();
922 }
923 
924 
926 {
927  NETCLASSPTR netclass = GetNetClasses().Find( m_currentNetClassName );
928 
929  return netclass->GetuViaDrill();
930 }
931 
932 
934 {
935  m_viaSizeIndex = std::min( aIndex, (unsigned) m_ViasDimensionsList.size() );
936  m_useCustomTrackVia = false;
937 }
938 
939 
941 {
942  if( m_useCustomTrackVia )
944  else if( m_viaSizeIndex == 0 )
946  else
947  return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter;
948 }
949 
950 
952 {
953  int drill;
954 
955  if( m_useCustomTrackVia )
956  drill = m_customViaSize.m_Drill;
957  else if( m_viaSizeIndex == 0 )
958  drill = GetNetClasses().GetDefaultPtr()->GetViaDrill();
959  else
960  drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill;
961 
962  return drill > 0 ? drill : -1;
963 }
964 
965 
967 {
968  m_trackWidthIndex = std::min( aIndex, (unsigned) m_TrackWidthList.size() );
969  m_useCustomTrackVia = false;
970 }
971 
972 
974 {
975  if( m_useCustomTrackVia )
976  return m_customTrackWidth;
977  else if( m_trackWidthIndex == 0 )
979  else
981 }
982 
983 
985 {
986  m_diffPairIndex = std::min( aIndex, (unsigned) 8 );
987  m_useCustomDiffPair = false;
988 }
989 
990 
992 {
993  if( m_useCustomDiffPair )
994  {
995  return m_customDiffPair.m_Width;
996  }
997  else if( m_diffPairIndex == 0 )
998  {
999  if( GetNetClasses().GetDefaultPtr()->HasDiffPairWidth() )
1001  else
1003  }
1004  else
1005  {
1006  return m_DiffPairDimensionsList[m_diffPairIndex].m_Width;
1007  }
1008 }
1009 
1010 
1012 {
1013  if( m_useCustomDiffPair )
1014  {
1015  return m_customDiffPair.m_Gap;
1016  }
1017  else if( m_diffPairIndex == 0 )
1018  {
1019  if( GetNetClasses().GetDefaultPtr()->HasDiffPairGap() )
1021  else
1023  }
1024  else
1025  {
1027  }
1028 }
1029 
1030 
1032 {
1033  if( m_useCustomDiffPair )
1034  {
1035  return m_customDiffPair.m_ViaGap;
1036  }
1037  else if( m_diffPairIndex == 0 )
1038  {
1039  if( GetNetClasses().GetDefaultPtr()->HasDiffPairViaGap() )
1041  else
1042  return GetCurrentDiffPairGap();
1043  }
1044  else
1045  {
1046  return m_DiffPairDimensionsList[m_diffPairIndex].m_ViaGap;
1047  }
1048 }
1049 
1050 
1052 {
1053  m_HoleToHoleMin = aDistance;
1054 }
1055 
1056 
1058 {
1059  m_CopperEdgeClearance = aDistance;
1060 }
1061 
1062 
1064 {
1065  m_SilkClearance = aDistance;
1066 }
1067 
1068 
1070 {
1071  m_copperLayerCount = aNewLayerCount;
1072 
1073  // Update only enabled copper layers mask
1074  m_enabledLayers &= ~LSET::AllCuMask();
1075 
1076  if( aNewLayerCount > 0 )
1077  m_enabledLayers |= LSET::AllCuMask( aNewLayerCount );
1078 }
1079 
1080 
1082 {
1083  // Back and front layers are always enabled.
1084  aMask.set( B_Cu ).set( F_Cu );
1085 
1086  m_enabledLayers = aMask;
1087 
1088  // update m_CopperLayerCount to ensure its consistency with m_EnabledLayers
1089  m_copperLayerCount = ( aMask & LSET::AllCuMask() ).count();
1090 }
1091 
1092 
1093 // Return the layer class index { silk, copper, edges & courtyards, fab, others } of the
1094 // given layer.
1096 {
1097  if( aLayer == F_SilkS || aLayer == B_SilkS )
1098  return LAYER_CLASS_SILK;
1099  else if( IsCopperLayer( aLayer ) )
1100  return LAYER_CLASS_COPPER;
1101  else if( aLayer == Edge_Cuts )
1102  return LAYER_CLASS_EDGES;
1103  else if( aLayer == F_CrtYd || aLayer == B_CrtYd )
1104  return LAYER_CLASS_COURTYARD;
1105  else if( aLayer == F_Fab || aLayer == B_Fab )
1106  return LAYER_CLASS_FAB;
1107  else
1108  return LAYER_CLASS_OTHERS;
1109 }
1110 
1111 
1113 {
1114  return Millimeter2iu( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
1115 }
1116 
1117 
1119 {
1120  return Millimeter2iu( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
1121 }
1122 
1123 
1125 {
1126  return m_LineThickness[ GetLayerClass( aLayer ) ];
1127 }
1128 
1129 
1131 {
1132  return m_TextSize[ GetLayerClass( aLayer ) ];
1133 }
1134 
1135 
1137 {
1138  return m_TextThickness[ GetLayerClass( aLayer ) ];
1139 }
1140 
1141 
1143 {
1144  return m_TextItalic[ GetLayerClass( aLayer ) ];
1145 }
1146 
1147 
1149 {
1150  return m_TextUpright[ GetLayerClass( aLayer ) ];
1151 }
1152 
1153 
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
#define DEFAULT_EDGE_WIDTH
#define DEFAULT_SILK_TEXT_WIDTH
void SetCopperLayerCount(int aNewLayerCount)
Set the copper layer count to aNewLayerCount.
#define DEFAULT_TRACKMINWIDTH
Container to handle a stock of specific vias each with unique diameter and drill sizes in the BOARD c...
int m_ZoneFillVersion
Option to select different fill algorithms.
void SetEnabledLayers(LSET aMask)
Change the bit-mask of enabled layers to aMask.
void SetCopperEdgeClearance(int aDistance)
#define DEFAULT_COURTYARD_WIDTH
void SetTrackWidthIndex(unsigned aIndex)
Set the current track width list index to aIndex.
void Set(const std::string &aPath, ValueType aVal)
Stores a value into the JSON document Will throw an exception if ValueType isn't something that the l...
wxString m_currentNetClassName
Current net class name used to display netclass info.
std::vector< TEXT_ITEM_INFO > m_DefaultFPTextItems
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition: drc_item.cpp:266
#define DEFAULT_SOLDERPASTE_RATIO
wxPoint m_GridOrigin
origin for grid offsets
NETCLASSPTR Find(const wxString &aName) const
Search this container for a NETCLASS given by aName.
Definition: netclass.cpp:132
int GetDiffPairGap() const
Definition: netclass.h:152
JSON_SETTINGS * GetParent()
#define DEFAULT_VIASMINSIZE
#define TEXTS_MAX_WIDTH
Maximum text width in internal units (10 inches)
Definition: pcbnew.h:33
BOARD_DESIGN_SETTINGS(JSON_SETTINGS *aParent, const std::string &aPath)
MINOPTMAX< int > & Value()
Definition: drc_rule.h:123
std::vector< int > m_TrackWidthList
BOARD_STACKUP m_stackup
the description of layers stackup, for board fabrication only physical layers are in layers stackup.
static constexpr double IU_PER_MM
Mock up a conversion function.
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
int GetHolePlatingThickness() const
Pad & via drills are finish size.
A holder for a rule check item, DRC in Pcbnew or ERC in Eeschema.
Definition: rc_item.h:74
NETCLASSES m_internalNetClasses
Net classes that are loaded from the board file before these were stored in the project.
bool Ignore(int aDRCErrorCode)
Return true if the DRC error code's severity is SEVERITY_IGNORE.
#define LEGACY_COPPEREDGECLEARANCE
#define DEFAULT_BOARD_THICKNESS_MM
int m_DimensionPrecision
Number of digits after the decimal.
ZONE_SETTINGS m_defaultZoneSettings
The default settings that will be used for new zones.
#define DEFAULT_LINE_WIDTH
#define DEFAULT_DIMENSION_ARROW_LENGTH
#define DEFAULT_COPPER_LINE_WIDTH
#define DEFAULT_HOLETOHOLEMIN
Text appears outside the dimension line (default)
Stores an enum as an integer.
Definition: parameters.h:215
T Min() const
Definition: minoptmax.h:33
DIFF_PAIR_DIMENSION m_customDiffPair
#define DEFAULT_CUSTOMDPAIRGAP
int GetTextThickness(PCB_LAYER_ID aLayer) const
Return the default text thickness from the layer class for the given layer.
static nlohmann::json::json_pointer PointerFromString(std::string aPath)
Builds a JSON pointer based on a given string.
VIATYPE m_CurrentViaType
(VIA_BLIND_BURIED, VIA_THROUGH, VIA_MICROVIA)
bool LoadFromFile(const wxString &aDirectory="") override
Loads the JSON document from the parent and then calls Load()
nlohmann::json json
Definition: gerbview.cpp:41
nlohmann::json & At(const std::string &aPath)
Wrappers for the underlying JSON API so that most consumers don't need json.hpp All of these function...
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:64
Container to handle a stock of specific differential pairs each with unique track width,...
std::unique_ptr< PAD > m_Pad_Master
#define DEFAULT_MINCLEARANCE
#define DEFAULT_MINTHROUGHDRILL
DIM_TEXT_POSITION m_DimensionTextPosition
DIM_UNITS_MODE m_DimensionUnitsMode
#define DEFAULT_CUSTOMDPAIRVIAGAP
int GetLayerClass(PCB_LAYER_ID aLayer) const
#define DEFAULT_DIMENSION_EXTENSION_OFFSET
bool GetTextUpright(PCB_LAYER_ID aLayer) const
Text appears in line with the dimension line.
#define DEFAULT_SOLDERPASTE_CLEARANCE
bool GetTextItalic(PCB_LAYER_ID aLayer) const
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
#define DEFAULT_TEXT_WIDTH
wxSize m_TextSize[LAYER_CLASS_COUNT]
void SetViaSizeIndex(unsigned aIndex)
Set the current via size list index to aIndex.
NESTED_SETTINGS is a JSON_SETTINGS that lives inside a JSON_SETTINGS.
#define DEFAULT_CUSTOMDPAIRWIDTH
int GetTrackWidth() const
Definition: netclass.h:128
#define DEFAULT_SILK_TEXT_SIZE
int m_TextThickness[LAYER_CLASS_COUNT]
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:504
#define DEFAULT_SILK_LINE_WIDTH
int GetDiffPairViaGap() const
Definition: netclass.h:156
std::unique_ptr< JSON_SETTINGS_INTERNALS > m_internals
void SetMinHoleSeparation(int aDistance)
bool LoadFromFile(const wxString &aDirectory="") override
Loads the backing file from disk and then calls Load()
JSON_SETTINGS * m_parent
A pointer to the parent object to load and store from.
int GetViaDrill() const
Definition: netclass.h:136
bool m_TextItalic[LAYER_CLASS_COUNT]
Represents a parameter that has a scaling factor between the value in the file and the value used int...
Definition: parameters.h:333
#define ZONE_CLEARANCE_MIL
Definition: zones.h:33
BOARD_DESIGN_SETTINGS & operator=(const BOARD_DESIGN_SETTINGS &aOther)
NETCLASSES & GetNetClasses() const
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
SEVERITY GetSeverity(int aDRCErrorCode)
const int bdsSchemaVersion
#define TEXTS_MAX_SIZE
Maximum text size in internal units (10 inches)
Definition: pcbnew.h:32
void SetDiffPairIndex(unsigned aIndex)
#define DEFAULT_MICROVIASMINSIZE
int GetDiffPairWidth() const
Definition: netclass.h:148
SEVERITY
NETCLASS * GetDefaultPtr() const
Definition: netclass.h:258
#define DEFAULT_MICROVIASMINDRILL
#define DEFAULT_SOLDERMASK_MIN_WIDTH
int m_LineThickness[LAYER_CLASS_COUNT]
#define DEFAULT_HOLECLEARANCE
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:796
#define TEXTS_MIN_SIZE
Minimum text size in internal units (1 mil)
Definition: pcbnew.h:31
#define DEFAULT_COPPEREDGECLEARANCE
bool m_UseHeightForLengthCalcs
Enable inclusion of stackup height in track length measurements and length tuning.
bool m_resetParamsIfMissing
Whether or not to set parameters to their default value if missing from JSON on Load()
wxString SeverityToString(const SEVERITY &aSeverity)
Definition: ui_common.cpp:59
const char * name
Definition: DXF_plotter.cpp:56
void registerMigration(int aOldSchemaVersion, int aNewSchemaVersion, std::function< bool(void)> aMigrator)
Registers a migration from one schema version to another.
#define DEFAULT_SILKCLEARANCE
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
int GetClearance() const
Definition: netclass.h:124
std::map< int, SEVERITY > m_DRCSeverities
SEVERITY SeverityFromString(const wxString &aSeverity)
Definition: ui_common.cpp:48
Definition: layer_ids.h:71
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition: drc_item.h:105
NETCLASS * GetDefault() const
int GetViaDiameter() const
Definition: netclass.h:132
void SetSilkClearance(int aDistance)
Set the minimum distance between silk items to aValue.
void initFromOther(const BOARD_DESIGN_SETTINGS &aOther)
#define DEFAULT_COPPER_TEXT_WIDTH
std::vector< VIA_DIMENSION > m_ViasDimensionsList
boost::optional< T > OPT
Definition: optional.h:7
#define DEFAULT_CUSTOMTRACKWIDTH
DIM_UNITS_FORMAT m_DimensionUnitsFormat
#define DEFAULT_TEXT_SIZE
Ratio of the font height to the baseline of the text above the wire.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
bool Contains(const std::string &aPath) const
NETCLASSES * m_netClasses
This will point to m_internalNetClasses until it is repointed to the project after load.
#define DEFAULT_SOLDERMASK_CLEARANCE
int m_copperLayerCount
Number of copper layers for this design.
#define DEFAULT_COPPER_TEXT_SIZE
bool m_MicroViasAllowed
true to allow micro vias
void ReleaseNestedSettings(NESTED_SETTINGS *aSettings)
Saves and frees a nested settings object, if it exists within this one.
std::set< wxString > m_DrcExclusions
static constexpr int Millimeter2iu(double mm)
LSET m_enabledLayers
Bit-mask for layer enabling.
wxPoint m_AuxOrigin
origin for plot exports
wxSize GetTextSize(PCB_LAYER_ID aLayer) const
Return the default text size from the layer class for the given layer.
int m_boardThickness
Board thickness for 3D viewer.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
virtual void Load()
Updates the parameters of this object based on the current JSON document contents.
bool m_TextUpright[LAYER_CLASS_COUNT]
Container for design settings for a BOARD object.