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
69 
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( wxEmptyString, true, F_Fab );
77  // Any following ones are freebies
78  m_DefaultFPTextItems.emplace_back( wxT( "${REFERENCE}" ), true, F_Fab );
79 
84  m_TextItalic[ LAYER_CLASS_SILK ] = false;
86 
93 
94  // Edges & Courtyards; text properties aren't used but better to have them holding
95  // reasonable values than not.
100  m_TextItalic[ LAYER_CLASS_EDGES ] = false;
101  m_TextUpright[ LAYER_CLASS_EDGES ] = false;
102 
109 
114  m_TextItalic[ LAYER_CLASS_FAB ] = false;
115  m_TextUpright[ LAYER_CLASS_FAB ] = false;
116 
121  m_TextItalic[ LAYER_CLASS_OTHERS ] = false;
123 
132 
133  m_useCustomTrackVia = false;
137 
138  m_useCustomDiffPair = false;
142 
154 
155  for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode )
156  m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
157 
159 
163 
166 
171 
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....
180 
181  // Global mask margins:
184 
185  // Solder paste margin absolute value
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
191 
192  // Layer thickness for 3D viewer
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,
217  MM_PER_IU ) );
218 
219  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_track_width", &m_TrackMinWidth,
221  MM_PER_IU ) );
222 
223  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_annular_width",
225  Millimeter2iu( 25.0 ), MM_PER_IU ) );
226 
227  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_via_diameter", &m_ViasMinSize,
229  MM_PER_IU ) );
230 
231  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_through_hole_diameter",
233  Millimeter2iu( 25.0 ), MM_PER_IU ) );
234 
235  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_diameter",
237  Millimeter2iu( 10.0 ), MM_PER_IU ) );
238 
239  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_microvia_drill", &m_MicroViasMinDrill,
241  Millimeter2iu( 10.0 ), MM_PER_IU ) );
242 
243  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_to_hole", &m_HoleToHoleMin,
245  MM_PER_IU ) );
246 
247  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_hole_clearance", &m_HoleClearance,
249  MM_PER_IU ) );
250 
251  m_params.emplace_back( new PARAM_SCALED<int>( "rules.min_silk_clearance", &m_SilkClearance,
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",
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",
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",
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",
442  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
443 
444  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.silk_text_thickness",
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",
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",
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",
464  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
465 
466  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.copper_text_thickness",
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",
478  Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ), MM_PER_IU ) );
479 
480  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.courtyard_line_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",
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",
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",
494  TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
495 
496  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.fab_text_thickness",
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",
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",
512  TEXTS_MAX_SIZE, MM_PER_IU ) );
513 
514  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_size_h",
516  TEXTS_MAX_SIZE, MM_PER_IU ) );
517 
518  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.other_text_thickness",
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",
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",
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",
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",
552  Mils2iu( DEFAULT_DIMENSION_ARROW_LENGTH ) ) );
553 
554  m_params.emplace_back( new PARAM<int>( "defaults.dimensions.extension_offset",
557 
558  m_params.emplace_back( new PARAM<bool>( "defaults.zones.45_degree_only",
560 
561  m_params.emplace_back( new PARAM_SCALED<int>( "defaults.zones.min_clearance",
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 
648 {
649  if( m_parent )
650  {
652  m_parent = nullptr;
653  }
654 }
655 
656 
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 
667 {
668  initFromOther( aOther );
669  return *this;
670 }
671 
672 
674 {
675  // Copy of NESTED_SETTINGS around is not allowed, so let's just update the params.
686  m_ViasMinSize = aOther.m_ViasMinSize;
698  m_MaxError = aOther.m_MaxError;
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 
728 
729  m_auxOrigin = aOther.m_auxOrigin;
730  m_gridOrigin = aOther.m_gridOrigin;
731  m_HasStackup = aOther.m_HasStackup;
733 
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 )
751  else
752  m_netClasses = aOther.m_netClasses;
753 
754  m_Pad_Master = std::make_unique<PAD>( *aOther.m_Pad_Master );
756 }
757 
758 
760 {
778  std::string units_ptr( "defaults.dimension_units" );
779  std::string precision_ptr( "defaults.dimension_precision" );
780 
781  if( !( Contains( units_ptr ) && Contains( precision_ptr ) &&
782  At( units_ptr ).is_number_integer() &&
783  At( precision_ptr ).is_number_integer() ) )
784  {
785  // if either is missing or invalid, migration doesn't make sense
786  return true;
787  }
788 
789  int units = Get<int>( units_ptr ).value();
790  int precision = Get<int>( precision_ptr ).value();
791 
792  // The enum maps directly to precision if the units is mils
793  int extraDigits = 0;
794 
795  switch( units )
796  {
797  case 0: extraDigits = 3; break;
798  case 2: extraDigits = 2; break;
799  default: break;
800  }
801 
802  precision += extraDigits;
803 
804  Set( precision_ptr, precision );
805 
806  return true;
807 }
808 
809 
810 bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
811 {
812  bool ret = NESTED_SETTINGS::LoadFromFile( aDirectory );
813 
814  // A number of things won't have been translated by the PROJECT_FILE migration because of
815  // descoped objects required to decode this data. So, it will be in the legacy.pcbnew
816  // section and needs to be pulled out here
817 
818  PROJECT_FILE* project = dynamic_cast<PROJECT_FILE*>( GetParent() );
819 
820  if( !project )
821  return ret;
822 
823  bool migrated = false;
824 
825  auto drcName =
826  []( int aCode ) -> std::string
827  {
828  std::shared_ptr<DRC_ITEM> item = DRC_ITEM::Create( aCode );
829  wxString name = item->GetSettingsKey();
830  return std::string( name.ToUTF8() );
831  };
832 
833  std::string bp = "board.design_settings.rule_severities.";
834  std::string rs = "rule_severities.";
835 
836  if( OPT<bool> v = project->Get<bool>( bp + "legacy_no_courtyard_defined" ) )
837  {
838  if( *v )
839  Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
840  else
841  Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
842 
843  project->Internals()->erase( m_internals->PointerFromString( bp + "legacy_no_courtyard_defined" ) );
844  migrated = true;
845  }
846 
847  if( OPT<bool> v = project->Get<bool>( bp + "legacy_courtyards_overlap" ) )
848  {
849  if( *v )
850  Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
851  else
852  Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
853 
854  project->Internals()->erase( JSON_SETTINGS_INTERNALS::PointerFromString( bp + "legacy_courtyards_overlap" ) );
855  migrated = true;
856  }
857 
858  if( Contains( "legacy" ) )
859  {
860  // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
861  // so we do the same for legacy boards.
863 
864  project->At( "legacy" ).erase( "pcbnew" );
865  }
866 
867  // Now that we have everything, we need to load again
868  if( migrated )
869  Load();
870 
871  return ret;
872 }
873 
874 
876 {
877  return m_DRCSeverities[ aDRCErrorCode ];
878 }
879 
880 
881 bool BOARD_DESIGN_SETTINGS::Ignore( int aDRCErrorCode )
882 {
883  return m_DRCSeverities[ aDRCErrorCode ] == RPT_SEVERITY_IGNORE;
884 }
885 
886 
888 {
889  int biggest = 0;
890  DRC_CONSTRAINT constraint;
891 
892  if( m_DRCEngine )
893  {
894  m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
895  biggest = std::max( biggest, constraint.Value().Min() );
896 
897  m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
898  biggest = std::max( biggest, constraint.Value().Min() );
899 
900  m_DRCEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, constraint );
901  biggest = std::max( biggest, constraint.Value().Min() );
902  }
903 
904  return biggest;
905 }
906 
907 
909 {
910  int clearance = GetDefault()->GetClearance();
911 
912  for( const std::pair<const wxString, NETCLASSPTR>& netclass : GetNetClasses().NetClasses() )
913  clearance = std::min( clearance, netclass.second->GetClearance() );
914 
915  return clearance;
916 }
917 
918 
920 {
921  NETCLASSPTR netclass = GetNetClasses().Find( m_currentNetClassName );
922 
923  return netclass->GetuViaDiameter();
924 }
925 
926 
928 {
929  NETCLASSPTR netclass = GetNetClasses().Find( m_currentNetClassName );
930 
931  return netclass->GetuViaDrill();
932 }
933 
934 
936 {
937  m_viaSizeIndex = std::min( aIndex, (unsigned) m_ViasDimensionsList.size() );
938  m_useCustomTrackVia = false;
939 }
940 
941 
943 {
944  if( m_useCustomTrackVia )
946  else if( m_viaSizeIndex == 0 )
948  else
949  return m_ViasDimensionsList[ m_viaSizeIndex ].m_Diameter;
950 }
951 
952 
954 {
955  int drill;
956 
957  if( m_useCustomTrackVia )
958  drill = m_customViaSize.m_Drill;
959  else if( m_viaSizeIndex == 0 )
960  drill = GetNetClasses().GetDefaultPtr()->GetViaDrill();
961  else
962  drill = m_ViasDimensionsList[ m_viaSizeIndex ].m_Drill;
963 
964  return drill > 0 ? drill : -1;
965 }
966 
967 
969 {
970  m_trackWidthIndex = std::min( aIndex, (unsigned) m_TrackWidthList.size() );
971  m_useCustomTrackVia = false;
972 }
973 
974 
976 {
977  if( m_useCustomTrackVia )
978  return m_customTrackWidth;
979  else if( m_trackWidthIndex == 0 )
981  else
983 }
984 
985 
987 {
988  if( !m_DiffPairDimensionsList.empty() )
989  {
990  m_diffPairIndex = std::min( aIndex,
991  static_cast<unsigned>( m_DiffPairDimensionsList.size() ) - 1 );
992  }
993 
994  m_useCustomDiffPair = false;
995 }
996 
997 
999 {
1000  if( m_useCustomDiffPair )
1001  {
1002  return m_customDiffPair.m_Width;
1003  }
1004  else if( m_diffPairIndex == 0 )
1005  {
1006  if( GetNetClasses().GetDefaultPtr()->HasDiffPairWidth() )
1008  else
1010  }
1011  else
1012  {
1013  return m_DiffPairDimensionsList[m_diffPairIndex].m_Width;
1014  }
1015 }
1016 
1017 
1019 {
1020  if( m_useCustomDiffPair )
1021  {
1022  return m_customDiffPair.m_Gap;
1023  }
1024  else if( m_diffPairIndex == 0 )
1025  {
1026  if( GetNetClasses().GetDefaultPtr()->HasDiffPairGap() )
1028  else
1030  }
1031  else
1032  {
1034  }
1035 }
1036 
1037 
1039 {
1040  if( m_useCustomDiffPair )
1041  {
1042  return m_customDiffPair.m_ViaGap;
1043  }
1044  else if( m_diffPairIndex == 0 )
1045  {
1046  if( GetNetClasses().GetDefaultPtr()->HasDiffPairViaGap() )
1048  else
1049  return GetCurrentDiffPairGap();
1050  }
1051  else
1052  {
1053  return m_DiffPairDimensionsList[m_diffPairIndex].m_ViaGap;
1054  }
1055 }
1056 
1057 
1059 {
1060  m_HoleToHoleMin = aDistance;
1061 }
1062 
1063 
1065 {
1066  m_CopperEdgeClearance = aDistance;
1067 }
1068 
1069 
1071 {
1072  m_SilkClearance = aDistance;
1073 }
1074 
1075 
1077 {
1078  m_copperLayerCount = aNewLayerCount;
1079 
1080  // Update only enabled copper layers mask
1081  m_enabledLayers &= ~LSET::AllCuMask();
1082 
1083  if( aNewLayerCount > 0 )
1084  m_enabledLayers |= LSET::AllCuMask( aNewLayerCount );
1085 }
1086 
1087 
1089 {
1090  // Back and front layers are always enabled.
1091  aMask.set( B_Cu ).set( F_Cu );
1092 
1093  m_enabledLayers = aMask;
1094 
1095  // update m_CopperLayerCount to ensure its consistency with m_EnabledLayers
1096  m_copperLayerCount = ( aMask & LSET::AllCuMask() ).count();
1097 }
1098 
1099 
1100 // Return the layer class index { silk, copper, edges & courtyards, fab, others } of the
1101 // given layer.
1103 {
1104  if( aLayer == F_SilkS || aLayer == B_SilkS )
1105  return LAYER_CLASS_SILK;
1106  else if( IsCopperLayer( aLayer ) )
1107  return LAYER_CLASS_COPPER;
1108  else if( aLayer == Edge_Cuts )
1109  return LAYER_CLASS_EDGES;
1110  else if( aLayer == F_CrtYd || aLayer == B_CrtYd )
1111  return LAYER_CLASS_COURTYARD;
1112  else if( aLayer == F_Fab || aLayer == B_Fab )
1113  return LAYER_CLASS_FAB;
1114  else
1115  return LAYER_CLASS_OTHERS;
1116 }
1117 
1118 
1120 {
1121  return Millimeter2iu( ADVANCED_CFG::GetCfg().m_DRCEpsilon );
1122 }
1123 
1124 
1126 {
1127  return Millimeter2iu( ADVANCED_CFG::GetCfg().m_HoleWallThickness );
1128 }
1129 
1130 
1132 {
1133  return m_LineThickness[ GetLayerClass( aLayer ) ];
1134 }
1135 
1136 
1138 {
1139  return m_TextSize[ GetLayerClass( aLayer ) ];
1140 }
1141 
1142 
1144 {
1145  return m_TextThickness[ GetLayerClass( aLayer ) ];
1146 }
1147 
1148 
1150 {
1151  return m_TextItalic[ GetLayerClass( aLayer ) ];
1152 }
1153 
1154 
1156 {
1157  return m_TextUpright[ GetLayerClass( aLayer ) ];
1158 }
1159 
1160 
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:759
#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
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
wxPoint m_auxOrigin
origin for plot exports
#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:516
#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:808
#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.
wxPoint m_gridOrigin
origin for grid offsets
#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.
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.