KiCad PCB EDA Suite
lset.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) 2014 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
5  * Copyright (C) 2014-2020 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <bitset> // for bitset, __bitset<>::ref...
26 #include <cassert>
27 #include <cstdarg>
28 #include <iostream> // for string, endl, basic_ost...
29 #include <stddef.h> // for size_t
30 
31 #include <math/util.h> // for Clamp
32 #include <layers_id_colors_and_visibility.h> // for LSET, PCB_LAYER_ID, LSEQ
33 #include <macros.h> // for arrayDim
34 #include <wx/debug.h> // for wxASSERT, wxASSERT_MSG
35 #include <wx/wx.h> // for wxT, wxChar
36 
37 
38 LSET::LSET( const PCB_LAYER_ID* aArray, unsigned aCount ) :
39  BASE_SET()
40 {
41  for( unsigned i=0; i<aCount; ++i )
42  set( aArray[i] );
43 }
44 
45 
46 LSET::LSET( unsigned aIdCount, int aFirst, ... ) :
47  BASE_SET()
48 {
49  // The constructor, without the mandatory aFirst argument, could have been confused
50  // by the compiler with the LSET( PCB_LAYER_ID ). With aFirst, that ambiguity is not
51  // present. Therefore aIdCount must always be >=1.
52  wxASSERT_MSG( aIdCount > 0, wxT( "aIdCount must be >= 1" ) );
53 
54  set( aFirst );
55 
56  if( --aIdCount )
57  {
58  va_list ap;
59 
60  va_start( ap, aFirst );
61 
62  for( unsigned i=0; i<aIdCount; ++i )
63  {
64  PCB_LAYER_ID id = (PCB_LAYER_ID) va_arg( ap, int );
65 
66  assert( unsigned( id ) < PCB_LAYER_ID_COUNT );
67 
68  set( id );
69  }
70 
71  va_end( ap );
72  }
73 }
74 
75 
81 const wxChar* LSET::Name( PCB_LAYER_ID aLayerId )
82 {
83  const wxChar* txt;
84 
85  // using a switch to explicitly show the mapping more clearly
86  switch( aLayerId )
87  {
88  case F_Cu: txt = wxT( "F.Cu" ); break;
89  case In1_Cu: txt = wxT( "In1.Cu" ); break;
90  case In2_Cu: txt = wxT( "In2.Cu" ); break;
91  case In3_Cu: txt = wxT( "In3.Cu" ); break;
92  case In4_Cu: txt = wxT( "In4.Cu" ); break;
93  case In5_Cu: txt = wxT( "In5.Cu" ); break;
94  case In6_Cu: txt = wxT( "In6.Cu" ); break;
95  case In7_Cu: txt = wxT( "In7.Cu" ); break;
96  case In8_Cu: txt = wxT( "In8.Cu" ); break;
97  case In9_Cu: txt = wxT( "In9.Cu" ); break;
98  case In10_Cu: txt = wxT( "In10.Cu" ); break;
99  case In11_Cu: txt = wxT( "In11.Cu" ); break;
100  case In12_Cu: txt = wxT( "In12.Cu" ); break;
101  case In13_Cu: txt = wxT( "In13.Cu" ); break;
102  case In14_Cu: txt = wxT( "In14.Cu" ); break;
103  case In15_Cu: txt = wxT( "In15.Cu" ); break;
104  case In16_Cu: txt = wxT( "In16.Cu" ); break;
105  case In17_Cu: txt = wxT( "In17.Cu" ); break;
106  case In18_Cu: txt = wxT( "In18.Cu" ); break;
107  case In19_Cu: txt = wxT( "In19.Cu" ); break;
108  case In20_Cu: txt = wxT( "In20.Cu" ); break;
109  case In21_Cu: txt = wxT( "In21.Cu" ); break;
110  case In22_Cu: txt = wxT( "In22.Cu" ); break;
111  case In23_Cu: txt = wxT( "In23.Cu" ); break;
112  case In24_Cu: txt = wxT( "In24.Cu" ); break;
113  case In25_Cu: txt = wxT( "In25.Cu" ); break;
114  case In26_Cu: txt = wxT( "In26.Cu" ); break;
115  case In27_Cu: txt = wxT( "In27.Cu" ); break;
116  case In28_Cu: txt = wxT( "In28.Cu" ); break;
117  case In29_Cu: txt = wxT( "In29.Cu" ); break;
118  case In30_Cu: txt = wxT( "In30.Cu" ); break;
119  case B_Cu: txt = wxT( "B.Cu" ); break;
120 
121  // Technicals
122  case B_Adhes: txt = wxT( "B.Adhes" ); break;
123  case F_Adhes: txt = wxT( "F.Adhes" ); break;
124  case B_Paste: txt = wxT( "B.Paste" ); break;
125  case F_Paste: txt = wxT( "F.Paste" ); break;
126  case B_SilkS: txt = wxT( "B.SilkS" ); break;
127  case F_SilkS: txt = wxT( "F.SilkS" ); break;
128  case B_Mask: txt = wxT( "B.Mask" ); break;
129  case F_Mask: txt = wxT( "F.Mask" ); break;
130 
131  // Users
132  case Dwgs_User: txt = wxT( "Dwgs.User" ); break;
133  case Cmts_User: txt = wxT( "Cmts.User" ); break;
134  case Eco1_User: txt = wxT( "Eco1.User" ); break;
135  case Eco2_User: txt = wxT( "Eco2.User" ); break;
136  case Edge_Cuts: txt = wxT( "Edge.Cuts" ); break;
137  case Margin: txt = wxT( "Margin" ); break;
138 
139  // Footprint
140  case F_CrtYd: txt = wxT( "F.CrtYd" ); break;
141  case B_CrtYd: txt = wxT( "B.CrtYd" ); break;
142  case F_Fab: txt = wxT( "F.Fab" ); break;
143  case B_Fab: txt = wxT( "B.Fab" ); break;
144 
145  // User definable layers.
146  case User_1: txt = wxT( "User.1" ); break;
147  case User_2: txt = wxT( "User.2" ); break;
148  case User_3: txt = wxT( "User.3" ); break;
149  case User_4: txt = wxT( "User.4" ); break;
150  case User_5: txt = wxT( "User.5" ); break;
151  case User_6: txt = wxT( "User.6" ); break;
152  case User_7: txt = wxT( "User.7" ); break;
153  case User_8: txt = wxT( "User.8" ); break;
154  case User_9: txt = wxT( "User.9" ); break;
155 
156  // Rescue
157  case Rescue: txt = wxT( "Rescue" ); break;
158 
159  default:
160  std::cout << aLayerId << std::endl;
161  wxASSERT_MSG( 0, wxT( "aLayerId out of range" ) );
162  txt = wxT( "BAD INDEX!" ); break;
163  }
164 
165  return txt;
166 }
167 
168 
170 {
171  // desired sequence
172  static const PCB_LAYER_ID sequence[] = {
173  F_Cu,
174  In1_Cu,
175  In2_Cu,
176  In3_Cu,
177  In4_Cu,
178  In5_Cu,
179  In6_Cu,
180  In7_Cu,
181  In8_Cu,
182  In9_Cu,
183  In10_Cu,
184  In11_Cu,
185  In12_Cu,
186  In13_Cu,
187  In14_Cu,
188  In15_Cu,
189  In16_Cu,
190  In17_Cu,
191  In18_Cu,
192  In19_Cu,
193  In20_Cu,
194  In21_Cu,
195  In22_Cu,
196  In23_Cu,
197  In24_Cu,
198  In25_Cu,
199  In26_Cu,
200  In27_Cu,
201  In28_Cu,
202  In29_Cu,
203  In30_Cu,
204  B_Cu, // 31
205  };
206 
207  return Seq( sequence, arrayDim( sequence ) );
208 }
209 
210 
211 LSEQ LSET::Technicals( LSET aSetToOmit ) const
212 {
213  // desired sequence
214  static const PCB_LAYER_ID sequence[] = {
215  F_Adhes,
216  B_Adhes,
217  F_Paste,
218  B_Paste,
219  F_SilkS,
220  B_SilkS,
221  F_Mask,
222  B_Mask,
223  F_CrtYd,
224  B_CrtYd,
225  F_Fab,
226  B_Fab,
227  };
228 
229  LSET subset = ~aSetToOmit & *this;
230 
231  return subset.Seq( sequence, arrayDim( sequence ) );
232 }
233 
234 
236 {
237  // desired
238  static const PCB_LAYER_ID sequence[] = {
239  Dwgs_User,
240  Cmts_User,
241  Eco1_User,
242  Eco2_User,
243  Edge_Cuts,
244  Margin,
245  User_1,
246  User_2,
247  User_3,
248  User_4,
249  User_5,
250  User_6,
251  User_7,
252  User_8,
253  User_9
254  };
255 
256  return Seq( sequence, arrayDim( sequence ) );
257 }
258 
259 
261 {
262  static const PCB_LAYER_ID sequence[] = {
263  F_Adhes,
264  B_Adhes,
265  F_Paste,
266  B_Paste,
267  F_SilkS,
268  B_SilkS,
269  F_Mask,
270  B_Mask,
271  Dwgs_User,
272  Cmts_User,
273  Eco1_User,
274  Eco2_User,
275  Edge_Cuts,
276  Margin,
277  F_CrtYd,
278  B_CrtYd,
279  F_Fab,
280  B_Fab,
281  User_1,
282  User_2,
283  User_3,
284  User_4,
285  User_5,
286  User_6,
287  User_7,
288  User_8,
289  User_9
290  };
291 
292  return Seq( sequence, arrayDim( sequence ) );
293 }
294 
295 
296 std::string LSET::FmtBin() const
297 {
298  std::string ret;
299 
300  int bit_count = size();
301 
302  for( int bit=0; bit<bit_count; ++bit )
303  {
304  if( bit )
305  {
306  if( !( bit % 8 ) )
307  ret += '|';
308  else if( !( bit % 4 ) )
309  ret += '_';
310  }
311 
312  ret += (*this)[bit] ? '1' : '0';
313  }
314 
315  // reverse of string
316  return std::string( ret.rbegin(), ret.rend() );
317 }
318 
319 
320 std::string LSET::FmtHex() const
321 {
322  std::string ret;
323 
324  static const char hex[] = "0123456789abcdef";
325 
326  size_t nibble_count = ( size() + 3 ) / 4;
327 
328  for( size_t nibble = 0; nibble < nibble_count; ++nibble )
329  {
330  unsigned int ndx = 0;
331 
332  // test 4 consecutive bits and set ndx to 0-15
333  for( size_t nibble_bit = 0; nibble_bit < 4; ++nibble_bit )
334  {
335  size_t nibble_pos = nibble_bit + ( nibble * 4 );
336  // make sure it's not extra bits that don't exist in the bitset but need to in the
337  // hex format
338  if( nibble_pos >= size() )
339  break;
340 
341  if( ( *this )[nibble_pos] )
342  ndx |= ( 1 << nibble_bit );
343  }
344 
345  if( nibble && !( nibble % 8 ) )
346  ret += '_';
347 
348  assert( ndx < arrayDim( hex ) );
349 
350  ret += hex[ndx];
351  }
352 
353  // reverse of string
354  return std::string( ret.rbegin(), ret.rend() );
355 }
356 
357 
358 int LSET::ParseHex( const char* aStart, int aCount )
359 {
360  LSET tmp;
361 
362  const char* rstart = aStart + aCount - 1;
363  const char* rend = aStart - 1;
364 
365  const int bitcount = size();
366 
367  int nibble_ndx = 0;
368 
369  while( rstart > rend )
370  {
371  int cc = *rstart--;
372 
373  if( cc == '_' )
374  continue;
375 
376  int nibble;
377 
378  if( cc >= '0' && cc <= '9' )
379  nibble = cc - '0';
380  else if( cc >= 'a' && cc <= 'f' )
381  nibble = cc - 'a' + 10;
382  else if( cc >= 'A' && cc <= 'F' )
383  nibble = cc - 'A' + 10;
384  else
385  break;
386 
387  int bit = nibble_ndx * 4;
388 
389  for( int ndx=0; bit<bitcount && ndx<4; ++bit, ++ndx )
390  if( nibble & (1<<ndx) )
391  tmp.set( bit );
392 
393  if( bit >= bitcount )
394  break;
395 
396  ++nibble_ndx;
397  }
398 
399  int byte_count = aStart + aCount - 1 - rstart;
400 
401  assert( byte_count >= 0 );
402 
403  if( byte_count > 0 )
404  *this = tmp;
405 
406  return byte_count;
407 }
408 
409 
410 LSEQ LSET::Seq( const PCB_LAYER_ID* aWishListSequence, unsigned aCount ) const
411 {
412  LSEQ ret;
413 
414 #if defined(DEBUG) && 0
415  LSET dup_detector;
416 
417  for( unsigned i=0; i<aCount; ++i )
418  {
419  PCB_LAYER_ID id = aWishListSequence[i];
420 
421  if( test( id ) )
422  {
423  wxASSERT_MSG( !dup_detector[id], wxT( "Duplicate in aWishListSequence" ) );
424  dup_detector[id] = true;
425 
426  ret.push_back( id );
427  }
428  }
429 #else
430 
431  for( unsigned i=0; i<aCount; ++i )
432  {
433  PCB_LAYER_ID id = aWishListSequence[i];
434 
435  if( test( id ) )
436  ret.push_back( id );
437  }
438 #endif
439 
440  return ret;
441 }
442 
443 
445 {
446  LSEQ ret;
447 
448  ret.reserve( size() );
449 
450  for( unsigned i = 0; i < size(); ++i )
451  {
452  if( test( i ) )
453  ret.push_back( PCB_LAYER_ID( i ) );
454  }
455 
456  return ret;
457 }
458 
459 
461 {
462  // bottom-to-top stack-up layers
463  static const PCB_LAYER_ID sequence[] = {
464  B_Fab,
465  B_CrtYd,
466  B_Adhes,
467  B_SilkS,
468  B_Paste,
469  B_Mask,
470  B_Cu,
471  In30_Cu,
472  In29_Cu,
473  In28_Cu,
474  In27_Cu,
475  In26_Cu,
476  In25_Cu,
477  In24_Cu,
478  In23_Cu,
479  In22_Cu,
480  In21_Cu,
481  In20_Cu,
482  In19_Cu,
483  In18_Cu,
484  In17_Cu,
485  In16_Cu,
486  In15_Cu,
487  In14_Cu,
488  In13_Cu,
489  In12_Cu,
490  In11_Cu,
491  In10_Cu,
492  In9_Cu,
493  In8_Cu,
494  In7_Cu,
495  In6_Cu,
496  In5_Cu,
497  In4_Cu,
498  In3_Cu,
499  In2_Cu,
500  In1_Cu,
501  F_Cu,
502  F_Mask,
503  F_Paste,
504  F_SilkS,
505  F_Adhes,
506  F_CrtYd,
507  F_Fab,
508  Dwgs_User,
509  Cmts_User,
510  Eco1_User,
511  Eco2_User,
512  Margin,
513  Edge_Cuts,
514  };
515 
516  return Seq( sequence, arrayDim( sequence ) );
517 }
518 
519 
520 PCB_LAYER_ID FlipLayer( PCB_LAYER_ID aLayerId, int aCopperLayersCount )
521 {
522  switch( aLayerId )
523  {
524  case B_Cu: return F_Cu;
525  case F_Cu: return B_Cu;
526 
527  case B_SilkS: return F_SilkS;
528  case F_SilkS: return B_SilkS;
529 
530  case B_Adhes: return F_Adhes;
531  case F_Adhes: return B_Adhes;
532 
533  case B_Mask: return F_Mask;
534  case F_Mask: return B_Mask;
535 
536  case B_Paste: return F_Paste;
537  case F_Paste: return B_Paste;
538 
539  case B_CrtYd: return F_CrtYd;
540  case F_CrtYd: return B_CrtYd;
541 
542  case B_Fab: return F_Fab;
543  case F_Fab: return B_Fab;
544 
545  default: // change internal layer if aCopperLayersCount is >= 4
546  if( IsCopperLayer( aLayerId ) && aCopperLayersCount >= 4 )
547  {
548  // internal copper layers count is aCopperLayersCount-2
549  PCB_LAYER_ID fliplayer = PCB_LAYER_ID(aCopperLayersCount - 2 - ( aLayerId - In1_Cu ) );
550  // Ensure fliplayer has a value which does not crash Pcbnew:
551  if( fliplayer < F_Cu )
552  fliplayer = F_Cu;
553 
554  if( fliplayer > B_Cu )
555  fliplayer = B_Cu;
556 
557  return fliplayer;
558  }
559 
560  // No change for the other layers
561  return aLayerId;
562  }
563 }
564 
565 
566 LSET FlipLayerMask( LSET aMask, int aCopperLayersCount )
567 {
568  // layers on physical outside of a board:
569  const static LSET and_mask( 16, // !! update count
570  B_Cu, F_Cu,
571  B_SilkS, F_SilkS,
572  B_Adhes, F_Adhes,
573  B_Mask, F_Mask,
574  B_Paste, F_Paste,
575  B_Adhes, F_Adhes,
576  B_CrtYd, F_CrtYd,
577  B_Fab, F_Fab
578  );
579 
580  LSET newMask = aMask & ~and_mask;
581 
582  if( aMask[B_Cu] )
583  newMask.set( F_Cu );
584 
585  if( aMask[F_Cu] )
586  newMask.set( B_Cu );
587 
588  if( aMask[B_SilkS] )
589  newMask.set( F_SilkS );
590 
591  if( aMask[F_SilkS] )
592  newMask.set( B_SilkS );
593 
594  if( aMask[B_Adhes] )
595  newMask.set( F_Adhes );
596 
597  if( aMask[F_Adhes] )
598  newMask.set( B_Adhes );
599 
600  if( aMask[B_Mask] )
601  newMask.set( F_Mask );
602 
603  if( aMask[F_Mask] )
604  newMask.set( B_Mask );
605 
606  if( aMask[B_Paste] )
607  newMask.set( F_Paste );
608 
609  if( aMask[F_Paste] )
610  newMask.set( B_Paste );
611 
612  if( aMask[B_Adhes] )
613  newMask.set( F_Adhes );
614 
615  if( aMask[F_Adhes] )
616  newMask.set( B_Adhes );
617 
618  if( aMask[B_CrtYd] )
619  newMask.set( F_CrtYd );
620 
621  if( aMask[F_CrtYd] )
622  newMask.set( B_CrtYd );
623 
624  if( aMask[B_Fab] )
625  newMask.set( F_Fab );
626 
627  if( aMask[F_Fab] )
628  newMask.set( B_Fab );
629 
630  if( aCopperLayersCount >= 4 ) // Internal layers exist
631  {
632  LSET internalMask = aMask & LSET::InternalCuMask();
633 
634  if( internalMask != LSET::InternalCuMask() )
635  {
636  // the mask does not include all internal layers. Therefore
637  // the flipped mask for internal copper layers must be built
638  int innerLayerCnt = aCopperLayersCount -2;
639 
640  // the flipped mask is the innerLayerCnt bits rewritten in reverse order
641  // ( bits innerLayerCnt to 1 rewritten in bits 1 to innerLayerCnt )
642  for( int ii = 0; ii < innerLayerCnt; ii++ )
643  {
644  if( internalMask[innerLayerCnt - ii] )
645  {
646  newMask.set( ii + In1_Cu );
647  }
648  else
649  {
650  newMask.reset( ii + In1_Cu );
651  }
652  }
653  }
654  }
655 
656  return newMask;
657 }
658 
659 
661 {
662  unsigned set_count = count();
663 
664  if( !set_count )
665  return UNSELECTED_LAYER;
666  else if( set_count > 1 )
667  return UNDEFINED_LAYER;
668 
669  for( unsigned i=0; i < size(); ++i )
670  {
671  if( test( i ) )
672  return PCB_LAYER_ID( i );
673  }
674 
675  wxASSERT( 0 ); // set_count was verified as 1 above, what did you break?
676 
677  return UNDEFINED_LAYER;
678 }
679 
680 
682 {
683  static const PCB_LAYER_ID front_assembly[] = {
684  F_SilkS,
685  F_Mask,
686  F_Fab,
687  F_CrtYd
688  };
689 
690  static const LSET saved( front_assembly, arrayDim( front_assembly ) );
691  return saved;
692 }
693 
694 
696 {
697  static const PCB_LAYER_ID back_assembly[] = {
698  B_SilkS,
699  B_Mask,
700  B_Fab,
701  B_CrtYd
702  };
703 
704  static const LSET saved( back_assembly, arrayDim( back_assembly ) );
705  return saved;
706 }
707 
708 
710 {
711  static const PCB_LAYER_ID cu_internals[] = {
712  In1_Cu,
713  In2_Cu,
714  In3_Cu,
715  In4_Cu,
716  In5_Cu,
717  In6_Cu,
718  In7_Cu,
719  In8_Cu,
720  In9_Cu,
721  In10_Cu,
722  In11_Cu,
723  In12_Cu,
724  In13_Cu,
725  In14_Cu,
726  In15_Cu,
727  In16_Cu,
728  In17_Cu,
729  In18_Cu,
730  In19_Cu,
731  In20_Cu,
732  In21_Cu,
733  In22_Cu,
734  In23_Cu,
735  In24_Cu,
736  In25_Cu,
737  In26_Cu,
738  In27_Cu,
739  In28_Cu,
740  In29_Cu,
741  In30_Cu,
742  };
743 
744  static const LSET saved( cu_internals, arrayDim( cu_internals ) );
745  return saved;
746 }
747 
748 
749 LSET LSET::AllCuMask( int aCuLayerCount )
750 {
751  // retain all in static as the full set, which is a common case.
752  static const LSET all = InternalCuMask().set( F_Cu ).set( B_Cu );
753 
754  if( aCuLayerCount == MAX_CU_LAYERS )
755  return all;
756 
757  // subtract out some Cu layers not wanted in the mask.
758  LSET ret = all;
759  int clear_count = MAX_CU_LAYERS - aCuLayerCount;
760 
761  clear_count = Clamp( 0, clear_count, MAX_CU_LAYERS - 2 );
762 
763  for( LAYER_NUM elem=In30_Cu; clear_count; --elem, --clear_count )
764  {
765  ret.set( elem, false );
766  }
767 
768  return ret;
769 }
770 
771 
773 {
774  static const LSET saved = LSET().set() & ~AllCuMask();
775  return saved;
776 }
777 
778 
780 {
781  static const LSET saved( 2, F_Cu, B_Cu );
782  return saved;
783 }
784 
785 
787 {
788  static const LSET saved = LSET().set();
789  return saved;
790 }
791 
792 
794 {
795  static const LSET saved( 6, B_SilkS, B_Mask, B_Adhes, B_Paste, B_CrtYd, B_Fab );
796  return saved;
797 }
798 
800 {
801  static const LSET saved( 4, B_SilkS, B_Mask, B_Adhes, B_Paste );
802  return saved;
803 }
804 
806 {
807  static const LSET saved( 6, F_SilkS, F_Mask, F_Adhes, F_Paste, F_CrtYd, F_Fab );
808  return saved;
809 }
810 
811 
813 {
814  static const LSET saved( 4, F_SilkS, F_Mask, F_Adhes, F_Paste );
815  return saved;
816 }
817 
818 
820 {
821  static const LSET saved = BackTechMask() | FrontTechMask();
822  return saved;
823 }
824 
825 
827 {
828  static const LSET saved = BackBoardTechMask() | FrontBoardTechMask();
829  return saved;
830 }
831 
832 
834 {
835  static const LSET saved( 6,
836  Dwgs_User,
837  Cmts_User,
838  Eco1_User,
839  Eco2_User,
840  Edge_Cuts,
841  Margin
842  );
843 
844  return saved;
845 }
846 
847 
849 {
850  static const LSET saved( 9,
851  User_1,
852  User_2,
853  User_3,
854  User_4,
855  User_5,
856  User_6,
857  User_7,
858  User_8,
859  User_9
860  );
861 
862  return saved;
863 }
864 
865 
867 {
868  static const LSET saved = FrontTechMask().set( F_Cu );
869  return saved;
870 }
871 
872 
874 {
875  static const LSET saved = BackTechMask().set( B_Cu );
876  return saved;
877 }
878 
879 
881 {
882  static const LSET saved = InternalCuMask().set( Edge_Cuts ).set( Margin );
883  return saved;
884 }
885 
886 
888 {
889  static const LSET saved( 1, Edge_Cuts );
890  return saved;
891 }
892 
893 
895 {
896  LSEQ order = CuStack();
897  LSEQ techuser = TechAndUserUIOrder();
898  order.insert( order.end(), techuser.begin(), techuser.end() );
899 
900  return order;
901 }
902 
903 
905 {
906  wxASSERT( aLayer < GAL_LAYER_ID_END );
907  return PCB_LAYER_ID( aLayer );
908 }
909 
910 
911 GAL_SET::GAL_SET( const GAL_LAYER_ID* aArray, unsigned aCount ) : GAL_SET()
912 {
913  for( unsigned i = 0; i < aCount; ++i )
914  set( aArray[i] );
915 }
916 
917 
918 std::vector<GAL_LAYER_ID> GAL_SET::Seq() const
919 {
920  std::vector<GAL_LAYER_ID> ret;
921 
922  for( size_t i = 0; i < size(); ++i )
923  {
924  if( test( i ) )
925  ret.push_back( static_cast<GAL_LAYER_ID>( i + GAL_LAYER_ID_START ) );
926  }
927 
928  return ret;
929 }
930 
931 
933 {
934  static const GAL_LAYER_ID visible[] = {
935  LAYER_VIAS,
942  // LAYER_MOD_TEXT_INVISIBLE, // Invisible text hidden by default
943  LAYER_ANCHOR,
944  LAYER_PAD_FR,
945  LAYER_PAD_BK,
947  LAYER_GRID,
950  LAYER_MOD_FR,
951  LAYER_MOD_BK,
954  LAYER_TRACKS,
960  // LAYER_DRC_EXCLUSION, // DRC exclusions hidden by default
965  LAYER_CURSOR,
968  LAYER_PADS,
969  LAYER_ZONES,
970  };
971 
972  static const GAL_SET saved( visible, arrayDim( visible ) );
973  return saved;
974 }
static LSET UserDefinedLayers()
Return a mask with all of the allowable user defined layers.
Definition: lset.cpp:848
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:749
static LSET FrontBoardTechMask()
Return a mask holding technical layers used in a board fabrication (no CU layer) on front side.
Definition: lset.cpp:812
to draw blind/buried vias
LSEQ CuStack() const
Return a sequence of copper layers in starting from the front/top and extending to the back/bottom.
Definition: lset.cpp:169
show a marker on pads with no nets
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
Definition: lset.cpp:566
multilayer pads, usually with holes
static LSET ForbiddenFootprintLayers()
Layers which are not allowed within footprint definitions.
Definition: lset.cpp:880
to handle and draw images bitmaps
static LSET BackTechMask()
Return a mask holding all technical layers (no CU layer) on back side.
Definition: lset.cpp:793
handle color for not plated holes (holes, not pads)
anchor of items having an anchor point (texts, footprints)
Control for copper zone opacity/visibility (color ignored)
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:520
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:772
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
to draw via holes (pad holes do not use this layer)
show modules values (when texts are visibles)
static LSET FrontTechMask()
Return a mask holding all technical layers (no CU layer) on front side.
Definition: lset.cpp:805
LSEQ SeqStackupBottom2Top() const
Return the sequence that is typical for a bottom-to-top stack-up.
Definition: lset.cpp:460
LSEQ Users() const
*_User layers.
Definition: lset.cpp:235
Add new GAL layers here.
static LSET AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:819
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:410
static LSET FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
Definition: lset.cpp:866
This file contains miscellaneous commonly used macros and functions.
show modules on front
LSEQ TechAndUserUIOrder() const
Returns the technical and user layers in the order shown in layer widget.
Definition: lset.cpp:260
std::bitset< PCB_LAYER_ID_COUNT > BASE_SET
LSEQ Seq() const
Return a LSEQ from this LSET in ascending PCB_LAYER_ID order.
Definition: lset.cpp:444
static LSET BackAssembly()
Return a complete set of all bottom assembly layers which is all B_SilkS and B_Mask.
Definition: lset.cpp:695
PCB_LAYER_ID
A quick note on layer IDs:
LSET is a set of PCB_LAYER_IDs.
Auxiliary items (guides, rule, etc)
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition: lset.cpp:81
Meta control for all pads opacity/visibility (color ignored)
to draw usual through hole vias
Helper for storing and iterating over GAL_LAYER_IDs.
static LSET InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition: lset.cpp:709
static LSET ExternalCuMask()
Return a mask holding the Front and Bottom layers.
Definition: lset.cpp:779
static GAL_SET DefaultVisible()
Definition: lset.cpp:932
static LSET FrontAssembly()
Return a complete set of all top assembly layers which is all F_SilkS and F_Mask.
Definition: lset.cpp:681
static LSET AllLayersMask()
Definition: lset.cpp:786
LSEQ Technicals(LSET aSubToOmit=LSET()) const
Return a sequence of technical layers.
Definition: lset.cpp:211
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
int LAYER_NUM
This can be replaced with int and removed.
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:160
layer for drc markers with SEVERITY_WARNING
smd pads, front layer
Meta control for all vias opacity/visibility.
Board layer functions and definitions.
LSET()
Create an empty (cleared) set.
std::string FmtBin() const
Return a binary string showing contents of this LSEQ.
Definition: lset.cpp:296
PCB_LAYER_ID ExtractLayer() const
Find the first set PCB_LAYER_ID.
Definition: lset.cpp:660
static LSET BackBoardTechMask()
Return a mask holding technical layers used in a board fabrication (no CU layer) on Back side.
Definition: lset.cpp:799
std::string FmtHex() const
Return a hex string showing contents of this LSEQ.
Definition: lset.cpp:320
currently selected items overlay
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: util.h:46
static LSET BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
Definition: lset.cpp:873
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
static LSET AllBoardTechMask()
Return a mask holding board technical layers (no CU layer) on both side.
Definition: lset.cpp:826
std::vector< GAL_LAYER_ID > Seq() const
Definition: lset.cpp:918
static LSET ForbiddenTextLayers()
Layers which are allowed to have text on them.
Definition: lset.cpp:887
static LSET UserMask()
Definition: lset.cpp:833
LSEQ UIOrder() const
Definition: lset.cpp:894
int ParseHex(const char *aStart, int aCount)
Convert the output of FmtHex() and replaces this set's values with those given in the input string.
Definition: lset.cpp:358
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:904
show modules references (when texts are visibles)
layer for drc markers with SEVERITY_ERROR