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