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 <class_dimension.h>
25 #include <class_track.h>
27 #include <kiface_i.h>
28 #include <board_design_settings.h>
29 #include <drc/drc_item.h>
30 #include <drc/drc_engine.h>
31 #include <settings/parameters.h>
32 #include <project/project_file.h>
33 #include <advanced_config.h>
34 
35 const int bdsSchemaVersion = 1;
36 
37 
38 BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
39  NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aParent, aPath ),
40  m_Pad_Master( NULL )
41 {
42  // We want to leave alone parameters that aren't found in the project JSON as they may be
43  // initialized by the board file parser before NESTED_SETTINGS::LoadFromFile is called.
44  m_resetParamsIfMissing = false;
45 
46  // Create a default NETCLASS list so that things don't break horribly if there's no project
47  // loaded. This also is used during file load for legacy boards that have netclasses stored
48  // in the file. After load, this information will be moved to the project and the pointer
49  // updated.
51 
52  m_HasStackup = false; // no stackup defined by default
53 
54  LSET all_set = LSET().set();
55  m_enabledLayers = all_set; // All layers enabled at first.
56  // SetCopperLayerCount() will adjust this.
57 
58  SetCopperLayerCount( 2 ); // Default design is a double sided board
60 
61  // if true, when creating a new track starting on an existing track, use this track width
63 
65  m_MicroViasAllowed = false;
66 
67  // First is always the reference designator
68  m_DefaultFPTextItems.emplace_back( wxT( "REF**" ), true, F_SilkS );
69  // Second is always the value
70  m_DefaultFPTextItems.emplace_back( wxT( "" ), true, F_Fab );
71  // Any following ones are freebies
72  m_DefaultFPTextItems.emplace_back( wxT( "${REF}" ), true, F_Fab );
73 
78  m_TextItalic[ LAYER_CLASS_SILK ] = false;
80 
87 
88  // Edges & Courtyards; text properties aren't used but better to have them holding
89  // reasonable values than not.
96 
103 
108  m_TextItalic[ LAYER_CLASS_FAB ] = false;
109  m_TextUpright[ LAYER_CLASS_FAB ] = false;
110 
115  m_TextItalic[ LAYER_CLASS_OTHERS ] = false;
117 
126 
127  m_useCustomTrackVia = false;
131 
132  m_useCustomDiffPair = false;
136 
147 
148  for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode )
149  m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
150 
154 
157 
162 
163  m_MaxError = ARC_HIGH_DEF;
164  m_ZoneFillVersion = 6; // Use new algo by default to fill zones
165  m_ZoneKeepExternalFillets = false; // Use new algo by default. Legacy boards might
166  // want to set it to true for old algo....
167 
168  // Global mask margins:
171  m_SolderPasteMargin = 0; // Solder paste margin absolute value
172  m_SolderPasteMarginRatio = 0.0; // Solder paste margin as a ratio of pad size
173  // The final margin is the sum of these 2 values
174  // Usually < 0 because the mask is smaller than pad
175  // Layer thickness for 3D viewer
177 
178  m_viaSizeIndex = 0;
179  m_trackWidthIndex = 0;
180  m_diffPairIndex = 0;
181 
182  // Parameters stored in JSON in the project file
183 
184  // NOTE: Previously, BOARD_DESIGN_SETTINGS stored the basic board layer information (layer
185  // names and enable/disable state) in the project file even though this information is also
186  // stored in the board file. This was implemented for importing these settings from another
187  // project. Going forward, the import feature will just import from other board files (since
188  // we could have multi-board projects in the future anyway) so this functionality is dropped.
189 
190  m_params.emplace_back( new PARAM<bool>( "rules.allow_microvias", &m_MicroViasAllowed, false ) );
191 
192  m_params.emplace_back( new PARAM<bool>( "rules.allow_blind_buried_vias",
193  &m_BlindBuriedViaAllowed, false ) );
194 
195  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_clearance", &m_MinClearance,
197  MM_PER_IU ) );
198 
199  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_track_width", &m_TrackMinWidth,
201  MM_PER_IU ) );
202 
203  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_annular_width", &m_ViasMinAnnulus,
205  MM_PER_IU ) );
206 
207  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_diameter", &m_ViasMinSize,
209  MM_PER_IU ) );
210 
211  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_through_hole_diameter",
213  Millimeter2iu( 25.0 ), MM_PER_IU ) );
214 
215  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_diameter",
217  Millimeter2iu( 10.0 ), MM_PER_IU ) );
218 
219  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_drill", &m_MicroViasMinDrill,
221  Millimeter2iu( 10.0 ), MM_PER_IU ) );
222 
223  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_to_hole", &m_HoleToHoleMin,
225  MM_PER_IU ) );
226 
227  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_silk_clearance", &m_SilkClearance,
229  MM_PER_IU ) );
230 
231  // Note: a clearance of -0.01 is a flag indicating we should use the legacy (pre-6.0) method
232  // based on the edge cut thicknesses.
233  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_copper_edge_clearance",
235  Millimeter2iu( -0.01 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
236 
237  m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_mask_clearance",
239  Millimeter2iu( -1.0 ), Millimeter2iu( 1.0 ), MM_PER_IU ) );
240 
241  m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_mask_min_width",
243  Millimeter2iu( 1.0 ), MM_PER_IU ) );
244 
245  m_params.emplace_back( new PARAM_SCALED<int>( "rules.solder_paste_clearance",
247  Millimeter2iu( -1.0 ), Millimeter2iu( 1.0 ), MM_PER_IU ) );
248 
249  m_params.emplace_back( new PARAM<double>( "rules.solder_paste_margin_ratio",
251 
252  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
253  [&]() -> nlohmann::json
254  {
255  nlohmann::json ret = {};
256 
257  for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
258  {
259  int code = item.GetErrorCode();
260 
261  if( !m_DRCSeverities.count( code ) )
262  continue;
263 
264  wxString name = item.GetSettingsKey();
265 
266  ret[std::string( name.ToUTF8() )] =
267  SeverityToString( static_cast<SEVERITY>( m_DRCSeverities[code] ) );
268  }
269 
270  return ret;
271  },
272  [&]( const nlohmann::json& aJson )
273  {
274  if( !aJson.is_object() )
275  return;
276 
277  for( const RC_ITEM& item : DRC_ITEM::GetItemsWithSeverities() )
278  {
279  wxString name = item.GetSettingsKey();
280  std::string key( name.ToUTF8() );
281 
282  if( aJson.contains( key ) )
283  m_DRCSeverities[item.GetErrorCode()] = SeverityFromString( aJson[key] );
284  }
285  }, {} ) );
286 
287  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "drc_exclusions",
288  [&]() -> nlohmann::json
289  {
290  nlohmann::json js = nlohmann::json::array();
291 
292  for( const auto& entry : m_DrcExclusions )
293  js.push_back( entry );
294 
295  return js;
296  },
297  [&]( const nlohmann::json& aObj )
298  {
299  m_DrcExclusions.clear();
300 
301  if( !aObj.is_array() )
302  return;
303 
304  for( const nlohmann::json& entry : aObj )
305  {
306  if( entry.empty() )
307  continue;
308 
309  m_DrcExclusions.insert( entry.get<wxString>() );
310  }
311  },
312  {} ) );
313 
314  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "track_widths",
315  [&]() -> nlohmann::json
316  {
317  nlohmann::json js = nlohmann::json::array();
318 
319  for( const int& width : m_TrackWidthList )
320  js.push_back( Iu2Millimeter( width ) );
321 
322  return js;
323  },
324  [&]( const nlohmann::json& aJson )
325  {
326  if( !aJson.is_array() )
327  return;
328 
329  m_TrackWidthList.clear();
330 
331  for( const nlohmann::json& entry : aJson )
332  {
333  if( entry.empty() )
334  continue;
335 
336  m_TrackWidthList.emplace_back( Millimeter2iu( entry.get<double>() ) );
337  }
338  },
339  {} ) );
340 
341  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "via_dimensions",
342  [&]() -> nlohmann::json
343  {
344  nlohmann::json js = nlohmann::json::array();
345 
346  for( const auto& via : m_ViasDimensionsList )
347  {
348  nlohmann::json entry = {};
349 
350  entry["diameter"] = Iu2Millimeter( via.m_Diameter );
351  entry["drill"] = Iu2Millimeter( via.m_Drill );
352 
353  js.push_back( entry );
354  }
355 
356  return js;
357  },
358  [&]( const nlohmann::json& aObj )
359  {
360  if( !aObj.is_array() )
361  return;
362 
363  m_ViasDimensionsList.clear();
364 
365  for( const nlohmann::json& entry : aObj )
366  {
367  if( entry.empty() || !entry.is_object() )
368  continue;
369 
370  if( !entry.contains( "diameter" ) || !entry.contains( "drill" ) )
371  continue;
372 
373  int diameter = Millimeter2iu( entry["diameter"].get<double>() );
374  int drill = Millimeter2iu( entry["drill"].get<double>() );
375 
376  m_ViasDimensionsList.emplace_back( VIA_DIMENSION( diameter, drill ) );
377  }
378  },
379  {} ) );
380 
381  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "diff_pair_dimensions",
382  [&]() -> nlohmann::json
383  {
384  nlohmann::json js = nlohmann::json::array();
385 
386  for( const auto& pair : m_DiffPairDimensionsList )
387  {
388  nlohmann::json entry = {};
389 
390  entry["width"] = Iu2Millimeter( pair.m_Width );
391  entry["gap"] = Iu2Millimeter( pair.m_Gap );
392  entry["via_gap"] = Iu2Millimeter( pair.m_ViaGap );
393 
394  js.push_back( entry );
395  }
396 
397  return js;
398  },
399  [&]( const nlohmann::json& aObj )
400  {
401  if( !aObj.is_array() )
402  return;
403 
404  m_DiffPairDimensionsList.clear();
405 
406  for( const nlohmann::json& entry : aObj )
407  {
408  if( entry.empty() || !entry.is_object() )
409  continue;
410 
411  if( !entry.contains( "width" ) || !entry.contains( "gap" )
412  || !entry.contains( "via_gap" ) )
413  continue;
414 
415  int width = Millimeter2iu( entry["width"].get<int>() );
416  int gap = Millimeter2iu( entry["gap"].get<int>() );
417  int via_gap = Millimeter2iu( entry["via_gap"].get<int>() );
418 
419  m_DiffPairDimensionsList.emplace_back(
420  DIFF_PAIR_DIMENSION( width, gap, via_gap ) );
421  }
422  },
423  {} ) );
424 
425  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_line_width",
427  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
428 
429  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_v",
431  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
432 
433  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_size_h",
435  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
436 
437  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_thickness",
439  TEXTS_MAX_WIDTH, MM_PER_IU ) );
440 
441  m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_italic",
442  &m_TextItalic[LAYER_CLASS_SILK], false ) );
443 
444  m_params.emplace_back( new PARAM<bool>( "defaults.silk_text_upright",
445  &m_TextUpright[ LAYER_CLASS_SILK ], true ) );
446 
447  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_line_width",
449  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
450 
451  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_v",
453  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
454 
455  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_size_h",
457  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
458 
459  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_thickness",
461  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
462 
463  m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_italic",
464  &m_TextItalic[LAYER_CLASS_COPPER], false ) );
465 
466  m_params.emplace_back( new PARAM<bool>( "defaults.copper_text_upright",
467  &m_TextUpright[LAYER_CLASS_COPPER], true ) );
468 
469  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.board_outline_line_width",
471  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
472 
473  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.courtyard_line_width",
475  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
476 
477  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_line_width",
479  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
480 
481  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_v",
483  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
484 
485  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_size_h",
487  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
488 
489  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_thickness",
491  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
492 
493  m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_italic",
494  &m_TextItalic[LAYER_CLASS_FAB], false ) );
495 
496  m_params.emplace_back( new PARAM<bool>( "defaults.fab_text_upright",
497  &m_TextUpright[LAYER_CLASS_FAB], true ) );
498 
499  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_line_width",
501  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
502 
503  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_v",
505  TEXTS_MAX_SIZE, MM_PER_IU ) );
506 
507  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_h",
509  TEXTS_MAX_SIZE, MM_PER_IU ) );
510 
511  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_thickness",
513  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
514 
515  m_params.emplace_back( new PARAM<bool>( "defaults.other_text_italic",
516  &m_TextItalic[LAYER_CLASS_OTHERS], false ) );
517 
518  m_params.emplace_back( new PARAM<bool>( "defaults.other_text_upright",
519  &m_TextUpright[LAYER_CLASS_OTHERS], true ) );
520 
521  m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_MODE>( "defaults.dimension_units",
524 
525  m_params.emplace_back( new PARAM<int>( "defaults.dimension_precision",
526  &m_DimensionPrecision, 4, 0, 5 ) );
527 
528  m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_FORMAT>( "defaults.dimensions.units_format",
531 
532  m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.suppress_zeroes",
533  &m_DimensionSuppressZeroes, false ) );
534 
535  // NOTE: excluding DIM_TEXT_POSITION::MANUAL from the valid range here
536  m_params.emplace_back( new PARAM_ENUM<DIM_TEXT_POSITION>( "defaults.dimensions.text_position",
539 
540  m_params.emplace_back( new PARAM<bool>( "defaults.dimensions.keep_text_aligned",
541  &m_DimensionKeepTextAligned, true ) );
542 
543  m_params.emplace_back( new PARAM<int>( "defaults.dimensions.arrow_length",
545  Mils2iu( DEFAULT_DIMENSION_ARROW_LENGTH ) ) );
546 
547  m_params.emplace_back( new PARAM<int>( "defaults.dimensions.extension_offset",
550 
551  m_params.emplace_back( new PARAM<bool>( "defaults.zones.45_degree_only",
553 
554  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.zones.min_clearance",
556  Millimeter2iu( 0.0 ), Millimeter2iu( 25.0 ), MM_PER_IU ) );
557 
558  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "defaults.pads",
559  [&]() -> nlohmann::json
560  {
561  nlohmann::json ret =
562  {
563  { "width", Iu2Millimeter( m_Pad_Master.GetSize().x ) },
564  { "height", Iu2Millimeter( m_Pad_Master.GetSize().y ) },
565  { "drill", Iu2Millimeter( m_Pad_Master.GetDrillSize().x ) }
566  };
567 
568  return ret;
569  },
570  [&]( const nlohmann::json& aJson )
571  {
572  if( aJson.contains( "width" ) && aJson.contains( "height" )
573  && aJson.contains( "drill" ) )
574  {
575  wxSize sz;
576  sz.SetWidth( Millimeter2iu( aJson["width"].get<double>() ) );
577  sz.SetHeight( Millimeter2iu( aJson["height"].get<double>() ) );
578 
579  m_Pad_Master.SetSize( sz );
580 
581  int drill = Millimeter2iu( aJson["drill"].get<double>() );
582 
583  m_Pad_Master.SetDrillSize( wxSize( drill, drill ) );
584  }
585  }, {} ) );
586 
587  m_params.emplace_back( new PARAM_SCALED<int>( "rules.max_error", &m_MaxError, ARC_HIGH_DEF,
588  Millimeter2iu( 0.0001 ), Millimeter2iu( 1.0 ), MM_PER_IU ) );
589 
590  // TODO: replace with zones_fill_version parameter and migrate zones_use_no_outline?
591  m_params.emplace_back( new PARAM_LAMBDA<bool>( "zones_use_no_outline",
592  [this]() -> bool
593  {
594  return m_ZoneFillVersion >= 6;
595  },
596  [this]( bool aVal )
597  {
598  m_ZoneFillVersion = aVal ? 6 : 5;
599  },
600  6 ) );
601 
602  m_params.emplace_back( new PARAM<bool>( "zones_allow_external_fillets",
603  &m_ZoneKeepExternalFillets, false ) );
604 
605  registerMigration( 0, 1, std::bind( &BOARD_DESIGN_SETTINGS::migrateSchema0to1, this ) );
606 }
607 
608 
610 {
611  if( m_parent )
612  {
614  m_parent = nullptr;
615  }
616 }
617 
618 
620  NESTED_SETTINGS( "board_design_settings", bdsSchemaVersion, aOther.m_parent,
621  aOther.m_path ),
622  m_Pad_Master( nullptr )
623 {
624  initFromOther( aOther );
625 }
626 
627 
629 {
630  initFromOther( aOther );
631  return *this;
632 }
633 
634 
636 {
637  // Copy of NESTED_SETTINGS around is not allowed, so let's just update the params.
648  m_ViasMinSize = aOther.m_ViasMinSize;
659  m_MaxError = aOther.m_MaxError;
665 
666  std::copy( std::begin( aOther.m_LineThickness ), std::end( aOther.m_LineThickness ),
667  std::begin( m_LineThickness ) );
668 
669  std::copy( std::begin( aOther.m_TextSize ), std::end( aOther.m_TextSize ),
670  std::begin( m_TextSize ) );
671 
672  std::copy( std::begin( aOther.m_TextThickness ), std::end( aOther.m_TextThickness ),
673  std::begin( m_TextThickness ) );
674 
675  std::copy( std::begin( aOther.m_TextItalic ), std::end( aOther.m_TextItalic ),
676  std::begin( m_TextItalic ) );
677 
678  std::copy( std::begin( aOther.m_TextUpright ), std::end( aOther.m_TextUpright ),
679  std::begin( m_TextUpright ) );
680 
689 
690  m_AuxOrigin = aOther.m_AuxOrigin;
691  m_GridOrigin = aOther.m_GridOrigin;
692  m_HasStackup = aOther.m_HasStackup;
693 
706  m_stackup = aOther.m_stackup;
707 
708  // Only take the pointer from the other if it isn't the default
709  if( aOther.m_netClasses == &aOther.m_internalNetClasses )
711  else
712  m_netClasses = aOther.m_netClasses;
713 
715 }
716 
717 
719 {
737  nlohmann::json::json_pointer units_ptr( "/defaults/dimension_units" );
738  nlohmann::json::json_pointer precision_ptr( "/defaults/dimension_precision" );
739 
740  if( !( contains( units_ptr ) && contains( precision_ptr ) &&
741  at( units_ptr ).is_number_integer() &&
742  at( precision_ptr ).is_number_integer() ) )
743  {
744  // if either is missing or invalid, migration doesn't make sense
745  return true;
746  }
747 
748  int units = at( units_ptr ).get<int>();
749  int precision = at( precision_ptr ).get<int>();
750 
751  // The enum maps directly to precision if the units is mils
752  int extraDigits = 0;
753 
754  switch( units )
755  {
756  case 0: extraDigits = 3; break;
757  case 2: extraDigits = 2; break;
758  default: break;
759  }
760 
761  precision += extraDigits;
762 
763  ( *this )[precision_ptr] = precision;
764 
765  return true;
766 }
767 
768 
769 bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
770 {
771  bool ret = NESTED_SETTINGS::LoadFromFile( aDirectory );
772 
773  // A number of things won't have been translated by the PROJECT_FILE migration because of
774  // descoped objects required to decode this data. So, it will be in the legacy.pcbnew
775  // section and needs to be pulled out here
776 
777  PROJECT_FILE* project = dynamic_cast<PROJECT_FILE*>( GetParent() );
778 
779  if( !project )
780  return ret;
781 
782  bool migrated = false;
783 
784  auto drcName =
785  []( int aCode ) -> std::string
786  {
787  std::shared_ptr<DRC_ITEM> item = DRC_ITEM::Create( aCode );
788  wxString name = item->GetSettingsKey();
789  return std::string( name.ToUTF8() );
790  };
791 
792  std::string bp = "board.design_settings.rule_severities.";
793  std::string rs = "rule_severities.";
794 
795  if( OPT<bool> v =
796  project->Get<bool>( PointerFromString( bp + "legacy_no_courtyard_defined" ) ) )
797  {
798  if( *v )
799  ( *this )[PointerFromString( rs + drcName( DRCE_MISSING_COURTYARD ) )] = "error";
800  else
801  ( *this )[PointerFromString( rs + drcName( DRCE_MISSING_COURTYARD ) )] = "ignore";
802 
803  project->erase( PointerFromString( bp + "legacy_no_courtyard_defined" ) );
804  migrated = true;
805  }
806 
807  if( OPT<bool> v = project->Get<bool>( PointerFromString( bp + "legacy_courtyards_overlap" ) ) )
808  {
809  if( *v )
810  ( *this )[PointerFromString( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ) )] = "error";
811  else
812  ( *this )[PointerFromString( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ) )] = "ignore";
813 
814  project->erase( PointerFromString( bp + "legacy_courtyards_overlap" ) );
815  migrated = true;
816  }
817 
818  if( project->contains( "legacy" ) )
819  {
820  // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
821  // so we do the same for legacy boards.
823 
824  project->at( "legacy" ).erase( "pcbnew" );
825  }
826 
827  // Now that we have everything, we need to load again
828  if( migrated )
829  Load();
830 
831  return ret;
832 }
833 
834 
835 int BOARD_DESIGN_SETTINGS::GetSeverity( int aDRCErrorCode )
836 {
837  return m_DRCSeverities[ aDRCErrorCode ];
838 }
839 
840 
841 bool BOARD_DESIGN_SETTINGS::Ignore( int aDRCErrorCode )
842 {
843  return m_DRCSeverities[ aDRCErrorCode ] == RPT_SEVERITY_IGNORE;
844 }
845 
846 
848 {
849  DRC_CONSTRAINT constraint;
850 
851  if( m_DRCEngine )
852  {
853  m_DRCEngine->QueryWorstConstraint( DRC_CONSTRAINT_TYPE_CLEARANCE, constraint,
855  }
856 
857  return constraint.Value().HasMin() ? constraint.Value().Min() : 0;
858 }
859 
860 
862 {
863  int clearance = GetDefault()->GetClearance();
864 
865  for( const std::pair<const wxString, NETCLASSPTR>& netclass : GetNetClasses().NetClasses() )
866  clearance = std::min( clearance, netclass.second->GetClearance() );
867 
868  return clearance;
869 }
870 
871 
873 {
874  NETCLASSPTR netclass = GetNetClasses().Find( m_currentNetClassName );
875 
876  return netclass->GetuViaDiameter();
877 }
878 
879 
881 {
882  NETCLASSPTR netclass = GetNetClasses().Find( m_currentNetClassName );
883 
884  return netclass->GetuViaDrill();
885 }
886 
887 
889 {
890  m_viaSizeIndex = std::min( aIndex, (unsigned) m_ViasDimensionsList.size() );
891  m_useCustomTrackVia = false;
892 }
893 
894 
896 {
897  if( m_useCustomTrackVia )
899  else if( m_viaSizeIndex == 0 )
901  else
902  return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter;
903 }
904 
905 
907 {
908  int drill;
909 
910  if( m_useCustomTrackVia )
911  drill = m_customViaSize.m_Drill;
912  else if( m_viaSizeIndex == 0 )
913  drill = GetNetClasses().GetDefaultPtr()->GetViaDrill();
914  else
915  drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill;
916 
917  return drill > 0 ? drill : -1;
918 }
919 
920 
922 {
923  m_trackWidthIndex = std::min( aIndex, (unsigned) m_TrackWidthList.size() );
924  m_useCustomTrackVia = false;
925 }
926 
927 
929 {
930  if( m_useCustomTrackVia )
931  return m_customTrackWidth;
932  else if( m_trackWidthIndex == 0 )
934  else
936 }
937 
938 
940 {
941  m_diffPairIndex = std::min( aIndex, (unsigned) 8 );
942  m_useCustomDiffPair = false;
943 }
944 
945 
947 {
948  m_HoleToHoleMin = aDistance;
949 }
950 
951 
953 {
954  m_CopperEdgeClearance = aDistance;
955 }
956 
957 
959 {
960  m_SilkClearance = aDistance;
961 }
962 
963 
965 {
966  m_copperLayerCount = aNewLayerCount;
967 
968  // Update only enabled copper layers mask
969  m_enabledLayers &= ~LSET::AllCuMask();
970 
971  if( aNewLayerCount > 0 )
972  m_enabledLayers |= LSET::AllCuMask( aNewLayerCount );
973 }
974 
975 
977 {
978  // Back and front layers are always enabled.
979  aMask.set( B_Cu ).set( F_Cu );
980 
981  m_enabledLayers = aMask;
982 
983  // update m_CopperLayerCount to ensure its consistency with m_EnabledLayers
984  m_copperLayerCount = ( aMask & LSET::AllCuMask() ).count();
985 }
986 
987 
988 // Return the layer class index { silk, copper, edges & courtyards, fab, others } of the
989 // given layer.
991 {
992  if( aLayer == F_SilkS || aLayer == B_SilkS )
993  return LAYER_CLASS_SILK;
994  else if( IsCopperLayer( aLayer ) )
995  return LAYER_CLASS_COPPER;
996  else if( aLayer == Edge_Cuts )
997  return LAYER_CLASS_EDGES;
998  else if( aLayer == F_CrtYd || aLayer == B_CrtYd )
999  return LAYER_CLASS_COURTYARD;
1000  else if( aLayer == F_Fab || aLayer == B_Fab )
1001  return LAYER_CLASS_FAB;
1002  else
1003  return LAYER_CLASS_OTHERS;
1004 }
1005 
1006 
1008 {
1009  return Millimeter2iu( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
1010 }
1011 
1012 
1014 {
1015  return Millimeter2iu( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
1016 }
1017 
1018 
1020 {
1021  return m_LineThickness[ GetLayerClass( aLayer ) ];
1022 }
1023 
1024 
1026 {
1027  return m_TextSize[ GetLayerClass( aLayer ) ];
1028 }
1029 
1030 
1032 {
1033  return m_TextThickness[ GetLayerClass( aLayer ) ];
1034 }
1035 
1036 
1038 {
1039  return m_TextItalic[ GetLayerClass( aLayer ) ];
1040 }
1041 
1042 
1044 {
1045  return m_TextUpright[ GetLayerClass( aLayer ) ];
1046 }
1047 
1048 
int GetCurrentMicroViaSize()
Function GetCurrentMicroViaSize.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:749
#define DEFAULT_EDGE_WIDTH
#define DEFAULT_SILK_TEXT_WIDTH
void SetCopperLayerCount(int aNewLayerCount)
Function SetCopperLayerCount do what its name says...
#define DEFAULT_TRACKMINWIDTH
Struct VIA_DIMENSION is a small helper container to handle a stock of specific vias each with unique ...
void SetEnabledLayers(LSET aMask)
Function SetEnabledLayers changes the bit-mask of enabled layers.
void SetCopperEdgeClearance(int aDistance)
Function SetCopperEdgeClearance.
#define DEFAULT_COURTYARD_WIDTH
Text appears outside the dimension line (default)
void SetTrackWidthIndex(unsigned aIndex)
Function SetTrackWidthIndex sets the current track width list index to aIndex.
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:239
#define DEFAULT_SOLDERPASTE_RATIO
wxPoint m_GridOrigin
origin for grid offsets
NETCLASSPTR Find(const wxString &aName) const
Function Find searches this container for a NETCLASS given by aName.
Definition: netclass.cpp:132
bool HasMin() const
Definition: minoptmax.h:35
int GetCurrentViaDrill() const
Function GetCurrentViaDrill.
JSON_SETTINGS * GetParent()
int GetCurrentTrackWidth() const
Function GetCurrentTrackWidth.
#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:122
std::vector< int > m_TrackWidthList
int GetSmallestClearanceValue()
Function GetSmallestClearanceValue.
int GetBiggestClearanceValue()
Function GetBiggestClearanceValue.
BOARD_STACKUP m_stackup
the description of layers stackup, for board fabrication only physical layers are in layers stackup.
int GetCurrentMicroViaDrill()
Function GetCurrentMicroViaDrill.
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:72
NETCLASSES m_internalNetClasses
Net classes that are loaded from the board file before these were stored in the project.
bool Ignore(int aDRCErrorCode)
returns 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 defualt 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
Stores an enum as an integer.
Definition: parameters.h:226
void SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:240
T Min() const
Definition: minoptmax.h:31
DIFF_PAIR_DIMENSION m_customDiffPair
#define DEFAULT_CUSTOMDPAIRGAP
int GetTextThickness(PCB_LAYER_ID aLayer) const
Function GetTextThickness Returns the default text thickness from the layer class for the given layer...
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:39
PROJECT_FILE is the backing store for a PROJECT, in JSON format.
Definition: project_file.h:62
Struct DIFF_PAIR_DIMENSION is a small helper container to handle a stock of specific differential pai...
#define DEFAULT_MINCLEARANCE
#define DEFAULT_MINTHROUGHDRILL
A single base class (TRACK) represents both tracks and vias, with subclasses for curved tracks (ARC) ...
DIM_TEXT_POSITION m_DimensionTextPosition
DIM_UNITS_MODE m_DimensionUnitsMode
#define DEFAULT_CUSTOMDPAIRVIAGAP
OPT< ValueType > Get(const std::string &aPath) const
Fetches a value from within the JSON document.
int GetLayerClass(PCB_LAYER_ID aLayer) const
#define DEFAULT_DIMENSION_EXTENSION_OFFSET
bool GetTextUpright(PCB_LAYER_ID aLayer) const
#define DEFAULT_SOLDERPASTE_CLEARANCE
bool GetTextItalic(PCB_LAYER_ID aLayer) const
int GetLineThickness(PCB_LAYER_ID aLayer) const
Function GetLineThickness Returns the default graphic segment thickness from the layer class for the ...
#define DEFAULT_TEXT_WIDTH
wxSize m_TextSize[LAYER_CLASS_COUNT]
void SetViaSizeIndex(unsigned aIndex)
Function SetViaSizeIndex sets the current via size list index to aIndex.
NESTED_SETTINGS is a JSON_SETTINGS that lives inside a JSON_SETTINGS.
DIMENSION class definition.
#define DEFAULT_CUSTOMDPAIRWIDTH
PCB_LAYER_ID
A quick note on layer IDs:
int GetTrackWidth() const
Definition: netclass.h:163
#define DEFAULT_SILK_TEXT_SIZE
int m_TextThickness[LAYER_CLASS_COUNT]
LSET is a set of PCB_LAYER_IDs.
#define DEFAULT_SILK_LINE_WIDTH
#define NULL
void SetMinHoleSeparation(int aDistance)
Function SetMinHoleSeparation.
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:171
bool m_TextItalic[LAYER_CLASS_COUNT]
Text appears in line with the dimension line.
Represents a parameter that has a scaling factor between the value in the file and the value used int...
Definition: parameters.h:388
void SetSize(const wxSize &aSize)
Definition: class_pad.h:230
#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
const int bdsSchemaVersion
#define TEXTS_MAX_SIZE
Maximum text size in internal units (10 inches)
Definition: pcbnew.h:32
void SetDiffPairIndex(unsigned aIndex)
Function SetDiffPairIndex.
#define DEFAULT_MICROVIASMINSIZE
NETCLASS * GetDefaultPtr() const
Definition: netclass.h:271
#define DEFAULT_MICROVIASMINDRILL
#define DEFAULT_SOLDERMASK_MIN_WIDTH
int m_LineThickness[LAYER_CLASS_COUNT]
std::map< int, int > m_DRCSeverities
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:81
#define TEXTS_MIN_SIZE
Minimum text size in internal units (1 mil)
Definition: pcbnew.h:31
#define DEFAULT_COPPEREDGECLEARANCE
int GetCurrentViaSize() const
Function GetCurrentViaSize.
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:44
Board layer functions and definitions.
const char * name
Definition: DXF_plotter.cpp:59
void registerMigration(int aOldSchemaVersion, int aNewSchemaVersion, std::function< bool(void)> aMigrator)
Registers a migration from one schema version to another.
#define DEFAULT_SILKCLEARANCE
int GetClearance() const
Definition: netclass.h:159
SEVERITY SeverityFromString(const wxString &aSeverity)
Definition: ui_common.cpp:33
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition: drc_item.h:102
const wxSize & GetDrillSize() const
Definition: class_pad.h:241
NETCLASS * GetDefault() const
Function GetDefault.
int GetViaDiameter() const
Definition: netclass.h:167
void SetSilkClearance(int aDistance)
Function SetSilkEdgeClearance.
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
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
DIM_UNITS_FORMAT m_DimensionUnitsFormat
#define DEFAULT_TEXT_SIZE
The offset of the pin name string from the end of the pin in mils.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers of advanced config.
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
const wxSize & GetSize() const
Definition: class_pad.h:231
int GetSeverity(int aDRCErrorCode)
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)
static nlohmann::json::json_pointer PointerFromString(std::string aPath)
Builds a JSON pointer based on a given string.
LSET m_enabledLayers
Bit-mask for layer enabling.
wxPoint m_AuxOrigin
origin for plot exports
wxSize GetTextSize(PCB_LAYER_ID aLayer) const
Function GetTextSize Returns 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]
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.