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 <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  B_Fab,
466  B_CrtYd,
467  B_Adhes,
468  B_SilkS,
469  B_Paste,
470  B_Mask,
471  B_Cu,
472  In30_Cu,
473  In29_Cu,
474  In28_Cu,
475  In27_Cu,
476  In26_Cu,
477  In25_Cu,
478  In24_Cu,
479  In23_Cu,
480  In22_Cu,
481  In21_Cu,
482  In20_Cu,
483  In19_Cu,
484  In18_Cu,
485  In17_Cu,
486  In16_Cu,
487  In15_Cu,
488  In14_Cu,
489  In13_Cu,
490  In12_Cu,
491  In11_Cu,
492  In10_Cu,
493  In9_Cu,
494  In8_Cu,
495  In7_Cu,
496  In6_Cu,
497  In5_Cu,
498  In4_Cu,
499  In3_Cu,
500  In2_Cu,
501  In1_Cu,
502  F_Cu,
503  F_Mask,
504  F_Paste,
505  F_SilkS,
506  F_Adhes,
507  F_CrtYd,
508  F_Fab,
509  Dwgs_User,
510  Cmts_User,
511  Eco1_User,
512  Eco2_User,
513  Margin,
514  Edge_Cuts,
515  };
516 
517  return Seq( sequence, arrayDim( sequence ) );
518 }
519 
520 
521 PCB_LAYER_ID FlipLayer( PCB_LAYER_ID aLayerId, int aCopperLayersCount )
522 {
523  switch( aLayerId )
524  {
525  case B_Cu: return F_Cu;
526  case F_Cu: return B_Cu;
527 
528  case B_SilkS: return F_SilkS;
529  case F_SilkS: return B_SilkS;
530 
531  case B_Adhes: return F_Adhes;
532  case F_Adhes: return B_Adhes;
533 
534  case B_Mask: return F_Mask;
535  case F_Mask: return B_Mask;
536 
537  case B_Paste: return F_Paste;
538  case F_Paste: return B_Paste;
539 
540  case B_CrtYd: return F_CrtYd;
541  case F_CrtYd: return B_CrtYd;
542 
543  case B_Fab: return F_Fab;
544  case F_Fab: return B_Fab;
545 
546  default: // change internal layer if aCopperLayersCount is >= 4
547  if( IsCopperLayer( aLayerId ) && aCopperLayersCount >= 4 )
548  {
549  // internal copper layers count is aCopperLayersCount-2
550  PCB_LAYER_ID fliplayer = PCB_LAYER_ID(aCopperLayersCount - 2 - ( aLayerId - In1_Cu ) );
551  // Ensure fliplayer has a value which does not crash Pcbnew:
552  if( fliplayer < F_Cu )
553  fliplayer = F_Cu;
554 
555  if( fliplayer > B_Cu )
556  fliplayer = B_Cu;
557 
558  return fliplayer;
559  }
560 
561  // No change for the other layers
562  return aLayerId;
563  }
564 }
565 
566 
567 LSET FlipLayerMask( LSET aMask, int aCopperLayersCount )
568 {
569  // layers on physical outside of a board:
570  const static LSET and_mask( 16, // !! update count
571  B_Cu, F_Cu,
572  B_SilkS, F_SilkS,
573  B_Adhes, F_Adhes,
574  B_Mask, F_Mask,
575  B_Paste, F_Paste,
576  B_Adhes, F_Adhes,
577  B_CrtYd, F_CrtYd,
578  B_Fab, F_Fab
579  );
580 
581  LSET newMask = aMask & ~and_mask;
582 
583  if( aMask[B_Cu] )
584  newMask.set( F_Cu );
585 
586  if( aMask[F_Cu] )
587  newMask.set( B_Cu );
588 
589  if( aMask[B_SilkS] )
590  newMask.set( F_SilkS );
591 
592  if( aMask[F_SilkS] )
593  newMask.set( B_SilkS );
594 
595  if( aMask[B_Adhes] )
596  newMask.set( F_Adhes );
597 
598  if( aMask[F_Adhes] )
599  newMask.set( B_Adhes );
600 
601  if( aMask[B_Mask] )
602  newMask.set( F_Mask );
603 
604  if( aMask[F_Mask] )
605  newMask.set( B_Mask );
606 
607  if( aMask[B_Paste] )
608  newMask.set( F_Paste );
609 
610  if( aMask[F_Paste] )
611  newMask.set( B_Paste );
612 
613  if( aMask[B_Adhes] )
614  newMask.set( F_Adhes );
615 
616  if( aMask[F_Adhes] )
617  newMask.set( B_Adhes );
618 
619  if( aMask[B_CrtYd] )
620  newMask.set( F_CrtYd );
621 
622  if( aMask[F_CrtYd] )
623  newMask.set( B_CrtYd );
624 
625  if( aMask[B_Fab] )
626  newMask.set( F_Fab );
627 
628  if( aMask[F_Fab] )
629  newMask.set( B_Fab );
630 
631  if( aCopperLayersCount >= 4 ) // Internal layers exist
632  {
633  LSET internalMask = aMask & LSET::InternalCuMask();
634 
635  if( internalMask != LSET::InternalCuMask() )
636  {
637  // the mask does not include all internal layers. Therefore
638  // the flipped mask for internal copper layers must be built
639  int innerLayerCnt = aCopperLayersCount -2;
640 
641  // the flipped mask is the innerLayerCnt bits rewritten in reverse order
642  // ( bits innerLayerCnt to 1 rewritten in bits 1 to innerLayerCnt )
643  for( int ii = 0; ii < innerLayerCnt; ii++ )
644  {
645  if( internalMask[innerLayerCnt - ii] )
646  {
647  newMask.set( ii + In1_Cu );
648  }
649  else
650  {
651  newMask.reset( ii + In1_Cu );
652  }
653  }
654  }
655  }
656 
657  return newMask;
658 }
659 
660 
662 {
663  unsigned set_count = count();
664 
665  if( !set_count )
666  return UNSELECTED_LAYER;
667  else if( set_count > 1 )
668  return UNDEFINED_LAYER;
669 
670  for( unsigned i=0; i < size(); ++i )
671  {
672  if( test( i ) )
673  return PCB_LAYER_ID( i );
674  }
675 
676  wxASSERT( 0 ); // set_count was verified as 1 above, what did you break?
677 
678  return UNDEFINED_LAYER;
679 }
680 
681 
683 {
684  static const PCB_LAYER_ID front_assembly[] = {
685  F_SilkS,
686  F_Mask,
687  F_Fab,
688  F_CrtYd
689  };
690 
691  static const LSET saved( front_assembly, arrayDim( front_assembly ) );
692  return saved;
693 }
694 
695 
697 {
698  static const PCB_LAYER_ID back_assembly[] = {
699  B_SilkS,
700  B_Mask,
701  B_Fab,
702  B_CrtYd
703  };
704 
705  static const LSET saved( back_assembly, arrayDim( back_assembly ) );
706  return saved;
707 }
708 
709 
711 {
712  static const PCB_LAYER_ID cu_internals[] = {
713  In1_Cu,
714  In2_Cu,
715  In3_Cu,
716  In4_Cu,
717  In5_Cu,
718  In6_Cu,
719  In7_Cu,
720  In8_Cu,
721  In9_Cu,
722  In10_Cu,
723  In11_Cu,
724  In12_Cu,
725  In13_Cu,
726  In14_Cu,
727  In15_Cu,
728  In16_Cu,
729  In17_Cu,
730  In18_Cu,
731  In19_Cu,
732  In20_Cu,
733  In21_Cu,
734  In22_Cu,
735  In23_Cu,
736  In24_Cu,
737  In25_Cu,
738  In26_Cu,
739  In27_Cu,
740  In28_Cu,
741  In29_Cu,
742  In30_Cu,
743  };
744 
745  static const LSET saved( cu_internals, arrayDim( cu_internals ) );
746  return saved;
747 }
748 
749 
750 LSET LSET::AllCuMask( int aCuLayerCount )
751 {
752  // retain all in static as the full set, which is a common case.
753  static const LSET all = InternalCuMask().set( F_Cu ).set( B_Cu );
754 
755  if( aCuLayerCount == MAX_CU_LAYERS )
756  return all;
757 
758  // subtract out some Cu layers not wanted in the mask.
759  LSET ret = all;
760  int clear_count = MAX_CU_LAYERS - aCuLayerCount;
761 
762  clear_count = Clamp( 0, clear_count, MAX_CU_LAYERS - 2 );
763 
764  for( LAYER_NUM elem=In30_Cu; clear_count; --elem, --clear_count )
765  {
766  ret.set( elem, false );
767  }
768 
769  return ret;
770 }
771 
772 
774 {
775  static const LSET saved = LSET().set() & ~AllCuMask();
776  return saved;
777 }
778 
779 
781 {
782  static const LSET saved( 2, F_Cu, B_Cu );
783  return saved;
784 }
785 
786 
788 {
789  static const LSET saved = LSET().set();
790  return saved;
791 }
792 
793 
795 {
796  static const LSET saved( 6, B_SilkS, B_Mask, B_Adhes, B_Paste, B_CrtYd, B_Fab );
797  return saved;
798 }
799 
801 {
802  static const LSET saved( 4, B_SilkS, B_Mask, B_Adhes, B_Paste );
803  return saved;
804 }
805 
807 {
808  static const LSET saved( 6, F_SilkS, F_Mask, F_Adhes, F_Paste, F_CrtYd, F_Fab );
809  return saved;
810 }
811 
812 
814 {
815  static const LSET saved( 4, F_SilkS, F_Mask, F_Adhes, F_Paste );
816  return saved;
817 }
818 
819 
821 {
822  static const LSET saved = BackTechMask() | FrontTechMask();
823  return saved;
824 }
825 
826 
828 {
829  static const LSET saved = BackBoardTechMask() | FrontBoardTechMask();
830  return saved;
831 }
832 
833 
835 {
836  static const LSET saved( 6,
837  Dwgs_User,
838  Cmts_User,
839  Eco1_User,
840  Eco2_User,
841  Edge_Cuts,
842  Margin
843  );
844 
845  return saved;
846 }
847 
848 
850 {
851  static const LSET saved = AllBoardTechMask() | AllCuMask();
852  return saved;
853 }
854 
855 
857 {
858  static const LSET saved( 9,
859  User_1,
860  User_2,
861  User_3,
862  User_4,
863  User_5,
864  User_6,
865  User_7,
866  User_8,
867  User_9
868  );
869 
870  return saved;
871 }
872 
873 
875 {
876  static const LSET saved = FrontTechMask().set( F_Cu );
877  return saved;
878 }
879 
880 
882 {
883  static const LSET saved = BackTechMask().set( B_Cu );
884  return saved;
885 }
886 
887 
889 {
890  static const LSET saved = InternalCuMask();
891  return saved;
892 }
893 
894 
896 {
897  LSEQ order = CuStack();
898  LSEQ techuser = TechAndUserUIOrder();
899  order.insert( order.end(), techuser.begin(), techuser.end() );
900 
901  return order;
902 }
903 
904 
906 {
907  wxASSERT( aLayer < GAL_LAYER_ID_END );
908  return PCB_LAYER_ID( aLayer );
909 }
910 
911 
912 GAL_SET::GAL_SET( const GAL_LAYER_ID* aArray, unsigned aCount ) : GAL_SET()
913 {
914  for( unsigned i = 0; i < aCount; ++i )
915  set( aArray[i] );
916 }
917 
918 
919 std::vector<GAL_LAYER_ID> GAL_SET::Seq() const
920 {
921  std::vector<GAL_LAYER_ID> ret;
922 
923  for( size_t i = 0; i < size(); ++i )
924  {
925  if( test( i ) )
926  ret.push_back( static_cast<GAL_LAYER_ID>( i + GAL_LAYER_ID_START ) );
927  }
928 
929  return ret;
930 }
931 
932 
934 {
935  static const GAL_LAYER_ID visible[] = {
936  LAYER_VIAS,
943  // LAYER_MOD_TEXT_INVISIBLE, // Invisible text hidden by default
944  LAYER_ANCHOR,
945  LAYER_PAD_FR,
946  LAYER_PAD_BK,
948  LAYER_GRID,
951  LAYER_MOD_FR,
952  LAYER_MOD_BK,
955  LAYER_TRACKS,
963  // LAYER_DRC_EXCLUSION, // DRC exclusions hidden by default
968  LAYER_CURSOR,
971  LAYER_PADS,
972  LAYER_ZONES,
973  };
974 
975  static const GAL_SET saved( visible, arrayDim( visible ) );
976  return saved;
977 }
static LSET UserDefinedLayers()
Return a mask with all of the allowable user defined layers.
Definition: lset.cpp:856
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
static LSET FrontBoardTechMask()
Return a mask holding technical layers used in a board fabrication (no CU layer) on front side.
Definition: lset.cpp:813
currently selected items overlay
Definition: layer_ids.h:214
smd pads, front layer
Definition: layer_ids.h:197
to draw micro vias
Definition: layer_ids.h:189
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:217
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
Definition: lset.cpp:567
layer for drc markers with SEVERITY_ERROR
Definition: layer_ids.h:211
static LSET ForbiddenFootprintLayers()
Layers which are not allowed within footprint definitions.
Definition: lset.cpp:888
Meta control for all pads opacity/visibility (color ignored)
Definition: layer_ids.h:225
static LSET BackTechMask()
Return a mask holding all technical layers (no CU layer) on back side.
Definition: lset.cpp:794
PCB cursor.
Definition: layer_ids.h:216
show footprints values (when texts are visible)
Definition: layer_ids.h:205
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
Definition: layer_ids.h:184
smd pads, back layer
Definition: layer_ids.h:198
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:521
std::bitset< PCB_LAYER_ID_COUNT > BASE_SET
Definition: layer_ids.h:493
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:773
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:196
int LAYER_NUM
This can be replaced with int and removed.
Definition: layer_ids.h:40
static LSET FrontTechMask()
Return a mask holding all technical layers (no CU layer) on front side.
Definition: lset.cpp:806
show footprints on back
Definition: layer_ids.h:204
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:284
static LSET AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:820
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:874
to draw via holes (pad holes do not use this layer)
Definition: layer_ids.h:210
Control for copper zone opacity/visibility (color ignored)
Definition: layer_ids.h:226
This file contains miscellaneous commonly used macros and functions.
to draw usual through hole vias
Definition: layer_ids.h:191
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:696
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:502
handle color for not plated holes (holes, not pads)
Definition: layer_ids.h:192
#define MAX_CU_LAYERS
Definition: layer_ids.h:146
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:188
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:203
Helper for storing and iterating over GAL_LAYER_IDs.
Definition: layer_ids.h:278
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:710
static LSET ExternalCuMask()
Return a mask holding the Front and Bottom layers.
Definition: lset.cpp:780
static GAL_SET DefaultVisible()
Definition: lset.cpp:933
static LSET FrontAssembly()
Return a complete set of all top assembly layers which is all F_SilkS and F_Mask.
Definition: lset.cpp:682
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:787
to handle and draw images bitmaps
Definition: layer_ids.h:218
drawingsheet frame and titleblock
Definition: layer_ids.h:212
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:463
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:787
show a marker on pads with no nets
Definition: layer_ids.h:202
show footprints references (when texts are visible)
Definition: layer_ids.h:206
static LSET PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition: lset.cpp:849
LSET()
Create an empty (cleared) set.
Definition: layer_ids.h:519
multilayer pads, usually with holes
Definition: layer_ids.h:208
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:190
PCB_LAYER_ID ExtractLayer() const
Find the first set PCB_LAYER_ID.
Definition: lset.cpp:661
static LSET BackBoardTechMask()
Return a mask holding technical layers used in a board fabrication (no CU layer) on Back side.
Definition: lset.cpp:800
general purpose overlay
Definition: layer_ids.h:213
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:64
Definition: layer_ids.h:70
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:230
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:881
PCB background color.
Definition: layer_ids.h:215
static LSET AllBoardTechMask()
Return a mask holding board technical layers (no CU layer) on both side.
Definition: lset.cpp:827
std::vector< GAL_LAYER_ID > Seq() const
Definition: lset.cpp:919
GAL_SET & set()
Definition: layer_ids.h:294
to draw pad holes (plated)
Definition: layer_ids.h:209
static LSET UserMask()
Definition: lset.cpp:834
LSEQ UIOrder() const
Definition: lset.cpp:895
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:905