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 <layers_id_colors_and_visibility.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/wx.h> // for wxT, wxChar
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( 9,
852  User_1,
853  User_2,
854  User_3,
855  User_4,
856  User_5,
857  User_6,
858  User_7,
859  User_8,
860  User_9
861  );
862 
863  return saved;
864 }
865 
866 
868 {
869  static const LSET saved = FrontTechMask().set( F_Cu );
870  return saved;
871 }
872 
873 
875 {
876  static const LSET saved = BackTechMask().set( B_Cu );
877  return saved;
878 }
879 
880 
882 {
883  static const LSET saved = InternalCuMask();
884  return saved;
885 }
886 
887 
889 {
890  LSEQ order = CuStack();
891  LSEQ techuser = TechAndUserUIOrder();
892  order.insert( order.end(), techuser.begin(), techuser.end() );
893 
894  return order;
895 }
896 
897 
899 {
900  wxASSERT( aLayer < GAL_LAYER_ID_END );
901  return PCB_LAYER_ID( aLayer );
902 }
903 
904 
905 GAL_SET::GAL_SET( const GAL_LAYER_ID* aArray, unsigned aCount ) : GAL_SET()
906 {
907  for( unsigned i = 0; i < aCount; ++i )
908  set( aArray[i] );
909 }
910 
911 
912 std::vector<GAL_LAYER_ID> GAL_SET::Seq() const
913 {
914  std::vector<GAL_LAYER_ID> ret;
915 
916  for( size_t i = 0; i < size(); ++i )
917  {
918  if( test( i ) )
919  ret.push_back( static_cast<GAL_LAYER_ID>( i + GAL_LAYER_ID_START ) );
920  }
921 
922  return ret;
923 }
924 
925 
927 {
928  static const GAL_LAYER_ID visible[] = {
929  LAYER_VIAS,
936  // LAYER_MOD_TEXT_INVISIBLE, // Invisible text hidden by default
937  LAYER_ANCHOR,
938  LAYER_PAD_FR,
939  LAYER_PAD_BK,
941  LAYER_GRID,
944  LAYER_MOD_FR,
945  LAYER_MOD_BK,
948  LAYER_TRACKS,
954  // LAYER_DRC_EXCLUSION, // DRC exclusions hidden by default
959  LAYER_CURSOR,
962  LAYER_PADS,
963  LAYER_ZONES,
964  };
965 
966  static const GAL_SET saved( visible, arrayDim( visible ) );
967  return saved;
968 }
static LSET UserDefinedLayers()
Return a mask with all of the allowable user defined layers.
Definition: lset.cpp:849
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
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:170
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:567
multilayer pads, usually with holes
static LSET ForbiddenFootprintLayers()
Layers which are not allowed within footprint definitions.
Definition: lset.cpp:881
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:794
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:521
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:773
show footprints on back
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
to draw via holes (pad holes do not use this layer)
show footprints values (when texts are visibles)
static LSET FrontTechMask()
Return a mask holding all technical layers (no CU layer) on front side.
Definition: lset.cpp:806
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
Add new GAL layers here.
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:867
This file contains miscellaneous commonly used macros and functions.
show footprints on front
LSEQ TechAndUserUIOrder() const
Returns the technical and user layers in the order shown in layer widget.
Definition: lset.cpp:261
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: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
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:82
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:710
static LSET ExternalCuMask()
Return a mask holding the Front and Bottom layers.
Definition: lset.cpp:780
static GAL_SET DefaultVisible()
Definition: lset.cpp:926
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
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.
int LAYER_NUM
This can be replaced with int and removed.
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:297
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
std::string FmtHex() const
Return a hex string showing contents of this LSEQ.
Definition: lset.cpp:321
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:874
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:827
std::vector< GAL_LAYER_ID > Seq() const
Definition: lset.cpp:912
static LSET UserMask()
Definition: lset.cpp:834
LSEQ UIOrder() const
Definition: lset.cpp:888
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:898
show footprints references (when texts are visibles)
layer for drc markers with SEVERITY_ERROR