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-2022 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
39LSET::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
47LSET::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
82const 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
212LSEQ 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
297std::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
321std::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
359int 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
411LSEQ 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
445LSEQ LSET::Seq( const LSEQ& aSequence ) const
446{
447 LSEQ ret;
448
449 for( LSEQ seq = aSequence; seq; ++seq )
450 {
451 if( test( *seq ) )
452 ret.push_back( *seq );
453 }
454
455 return ret;
456}
457
458
460{
461 LSEQ ret;
462
463 ret.reserve( size() );
464
465 for( unsigned i = 0; i < size(); ++i )
466 {
467 if( test( i ) )
468 ret.push_back( PCB_LAYER_ID( i ) );
469 }
470
471 return ret;
472}
473
474
476{
477 // bottom-to-top stack-up layers
478 static const PCB_LAYER_ID sequence[] = {
479 User_9,
480 User_8,
481 User_7,
482 User_6,
483 User_5,
484 User_4,
485 User_3,
486 User_2,
487 User_1,
488 B_Fab,
489 B_CrtYd,
490 B_Adhes,
491 B_SilkS,
492 B_Paste,
493 B_Mask,
494 B_Cu,
495 In30_Cu,
496 In29_Cu,
497 In28_Cu,
498 In27_Cu,
499 In26_Cu,
500 In25_Cu,
501 In24_Cu,
502 In23_Cu,
503 In22_Cu,
504 In21_Cu,
505 In20_Cu,
506 In19_Cu,
507 In18_Cu,
508 In17_Cu,
509 In16_Cu,
510 In15_Cu,
511 In14_Cu,
512 In13_Cu,
513 In12_Cu,
514 In11_Cu,
515 In10_Cu,
516 In9_Cu,
517 In8_Cu,
518 In7_Cu,
519 In6_Cu,
520 In5_Cu,
521 In4_Cu,
522 In3_Cu,
523 In2_Cu,
524 In1_Cu,
525 F_Cu,
526 F_Mask,
527 F_Paste,
528 F_SilkS,
529 F_Adhes,
530 F_CrtYd,
531 F_Fab,
532 Dwgs_User,
533 Cmts_User,
534 Eco1_User,
535 Eco2_User,
536 Margin,
537 Edge_Cuts,
538 };
539
540 return Seq( sequence, arrayDim( sequence ) );
541}
542
543
544PCB_LAYER_ID FlipLayer( PCB_LAYER_ID aLayerId, int aCopperLayersCount )
545{
546 switch( aLayerId )
547 {
548 case B_Cu: return F_Cu;
549 case F_Cu: return B_Cu;
550
551 case B_SilkS: return F_SilkS;
552 case F_SilkS: return B_SilkS;
553
554 case B_Adhes: return F_Adhes;
555 case F_Adhes: return B_Adhes;
556
557 case B_Mask: return F_Mask;
558 case F_Mask: return B_Mask;
559
560 case B_Paste: return F_Paste;
561 case F_Paste: return B_Paste;
562
563 case B_CrtYd: return F_CrtYd;
564 case F_CrtYd: return B_CrtYd;
565
566 case B_Fab: return F_Fab;
567 case F_Fab: return B_Fab;
568
569 default: // change internal layer if aCopperLayersCount is >= 4
570 if( IsCopperLayer( aLayerId ) && aCopperLayersCount >= 4 )
571 {
572 // internal copper layers count is aCopperLayersCount-2
573 PCB_LAYER_ID fliplayer = PCB_LAYER_ID(aCopperLayersCount - 2 - ( aLayerId - In1_Cu ) );
574 // Ensure fliplayer has a value which does not crash Pcbnew:
575 if( fliplayer < F_Cu )
576 fliplayer = F_Cu;
577
578 if( fliplayer > B_Cu )
579 fliplayer = B_Cu;
580
581 return fliplayer;
582 }
583
584 // No change for the other layers
585 return aLayerId;
586 }
587}
588
589
590LSET FlipLayerMask( LSET aMask, int aCopperLayersCount )
591{
592 // layers on physical outside of a board:
593 const static LSET and_mask( 16, // !! update count
594 B_Cu, F_Cu,
597 B_Mask, F_Mask,
601 B_Fab, F_Fab
602 );
603
604 LSET newMask = aMask & ~and_mask;
605
606 if( aMask[B_Cu] )
607 newMask.set( F_Cu );
608
609 if( aMask[F_Cu] )
610 newMask.set( B_Cu );
611
612 if( aMask[B_SilkS] )
613 newMask.set( F_SilkS );
614
615 if( aMask[F_SilkS] )
616 newMask.set( B_SilkS );
617
618 if( aMask[B_Adhes] )
619 newMask.set( F_Adhes );
620
621 if( aMask[F_Adhes] )
622 newMask.set( B_Adhes );
623
624 if( aMask[B_Mask] )
625 newMask.set( F_Mask );
626
627 if( aMask[F_Mask] )
628 newMask.set( B_Mask );
629
630 if( aMask[B_Paste] )
631 newMask.set( F_Paste );
632
633 if( aMask[F_Paste] )
634 newMask.set( B_Paste );
635
636 if( aMask[B_Adhes] )
637 newMask.set( F_Adhes );
638
639 if( aMask[F_Adhes] )
640 newMask.set( B_Adhes );
641
642 if( aMask[B_CrtYd] )
643 newMask.set( F_CrtYd );
644
645 if( aMask[F_CrtYd] )
646 newMask.set( B_CrtYd );
647
648 if( aMask[B_Fab] )
649 newMask.set( F_Fab );
650
651 if( aMask[F_Fab] )
652 newMask.set( B_Fab );
653
654 if( aCopperLayersCount >= 4 ) // Internal layers exist
655 {
656 LSET internalMask = aMask & LSET::InternalCuMask();
657
658 if( internalMask != LSET::InternalCuMask() )
659 {
660 // the mask does not include all internal layers. Therefore
661 // the flipped mask for internal copper layers must be built
662 int innerLayerCnt = aCopperLayersCount -2;
663
664 // the flipped mask is the innerLayerCnt bits rewritten in reverse order
665 // ( bits innerLayerCnt to 1 rewritten in bits 1 to innerLayerCnt )
666 for( int ii = 0; ii < innerLayerCnt; ii++ )
667 {
668 if( internalMask[innerLayerCnt - ii] )
669 {
670 newMask.set( ii + In1_Cu );
671 }
672 else
673 {
674 newMask.reset( ii + In1_Cu );
675 }
676 }
677 }
678 }
679
680 return newMask;
681}
682
683
685{
686 unsigned set_count = count();
687
688 if( !set_count )
689 return UNSELECTED_LAYER;
690 else if( set_count > 1 )
691 return UNDEFINED_LAYER;
692
693 for( unsigned i=0; i < size(); ++i )
694 {
695 if( test( i ) )
696 return PCB_LAYER_ID( i );
697 }
698
699 wxASSERT( 0 ); // set_count was verified as 1 above, what did you break?
700
701 return UNDEFINED_LAYER;
702}
703
704
706{
707 static const PCB_LAYER_ID front_assembly[] = {
708 F_SilkS,
709 F_Mask,
710 F_Fab,
711 F_CrtYd
712 };
713
714 static const LSET saved( front_assembly, arrayDim( front_assembly ) );
715 return saved;
716}
717
718
720{
721 static const PCB_LAYER_ID back_assembly[] = {
722 B_SilkS,
723 B_Mask,
724 B_Fab,
725 B_CrtYd
726 };
727
728 static const LSET saved( back_assembly, arrayDim( back_assembly ) );
729 return saved;
730}
731
732
734{
735 static const PCB_LAYER_ID cu_internals[] = {
736 In1_Cu,
737 In2_Cu,
738 In3_Cu,
739 In4_Cu,
740 In5_Cu,
741 In6_Cu,
742 In7_Cu,
743 In8_Cu,
744 In9_Cu,
745 In10_Cu,
746 In11_Cu,
747 In12_Cu,
748 In13_Cu,
749 In14_Cu,
750 In15_Cu,
751 In16_Cu,
752 In17_Cu,
753 In18_Cu,
754 In19_Cu,
755 In20_Cu,
756 In21_Cu,
757 In22_Cu,
758 In23_Cu,
759 In24_Cu,
760 In25_Cu,
761 In26_Cu,
762 In27_Cu,
763 In28_Cu,
764 In29_Cu,
765 In30_Cu,
766 };
767
768 static const LSET saved( cu_internals, arrayDim( cu_internals ) );
769 return saved;
770}
771
772
773LSET LSET::AllCuMask( int aCuLayerCount )
774{
775 // retain all in static as the full set, which is a common case.
776 static const LSET all = InternalCuMask().set( F_Cu ).set( B_Cu );
777
778 if( aCuLayerCount == MAX_CU_LAYERS )
779 return all;
780
781 // subtract out some Cu layers not wanted in the mask.
782 LSET ret = all;
783 int clear_count = MAX_CU_LAYERS - aCuLayerCount;
784
785 clear_count = Clamp( 0, clear_count, MAX_CU_LAYERS - 2 );
786
787 for( int elem = In30_Cu; clear_count; --elem, --clear_count )
788 ret.set( elem, false );
789
790 return ret;
791}
792
793
795{
796 static const LSET saved = LSET().set() & ~AllCuMask();
797 return saved;
798}
799
800
802{
803 static const LSET saved( 2, F_Cu, B_Cu );
804 return saved;
805}
806
807
809{
810 static const LSET saved = LSET().set();
811 return saved;
812}
813
814
816{
817 static const LSET saved( 6, B_SilkS, B_Mask, B_Adhes, B_Paste, B_CrtYd, B_Fab );
818 return saved;
819}
820
822{
823 static const LSET saved( 4, B_SilkS, B_Mask, B_Adhes, B_Paste );
824 return saved;
825}
826
828{
829 static const LSET saved( 6, F_SilkS, F_Mask, F_Adhes, F_Paste, F_CrtYd, F_Fab );
830 return saved;
831}
832
833
835{
836 static const LSET saved( 4, F_SilkS, F_Mask, F_Adhes, F_Paste );
837 return saved;
838}
839
840
842{
843 static const LSET saved = BackTechMask() | FrontTechMask();
844 return saved;
845}
846
847
849{
850 static const LSET saved = BackBoardTechMask() | FrontBoardTechMask();
851 return saved;
852}
853
854
856{
857 static const LSET saved( 6,
858 Dwgs_User,
859 Cmts_User,
860 Eco1_User,
861 Eco2_User,
862 Edge_Cuts,
863 Margin
864 );
865
866 return saved;
867}
868
869
871{
872 static const LSET saved = AllBoardTechMask() | AllCuMask();
873 return saved;
874}
875
876
878{
879 static const LSET saved( 9,
880 User_1,
881 User_2,
882 User_3,
883 User_4,
884 User_5,
885 User_6,
886 User_7,
887 User_8,
888 User_9
889 );
890
891 return saved;
892}
893
894
896{
897 static const LSET saved = FrontTechMask().set( F_Cu );
898 return saved;
899}
900
901
903{
904 static const LSET saved = BackTechMask().set( B_Cu );
905 return saved;
906}
907
909{
910 static const LSET saved = BackTechMask() | FrontTechMask() | AllCuMask();
911 return saved;
912}
913
914
916{
917 static const LSET saved = InternalCuMask();
918 return saved;
919}
920
921
923{
924 LSEQ order = CuStack();
925 LSEQ techuser = TechAndUserUIOrder();
926 order.insert( order.end(), techuser.begin(), techuser.end() );
927
928 return order;
929}
930
931
933{
934 wxASSERT( aLayer < GAL_LAYER_ID_END );
935 return PCB_LAYER_ID( aLayer );
936}
937
938
939GAL_SET::GAL_SET( const GAL_LAYER_ID* aArray, unsigned aCount ) : GAL_SET()
940{
941 for( unsigned i = 0; i < aCount; ++i )
942 set( aArray[i] );
943}
944
945
946std::vector<GAL_LAYER_ID> GAL_SET::Seq() const
947{
948 std::vector<GAL_LAYER_ID> ret;
949
950 for( size_t i = 0; i < size(); ++i )
951 {
952 if( test( i ) )
953 ret.push_back( static_cast<GAL_LAYER_ID>( i + GAL_LAYER_ID_START ) );
954 }
955
956 return ret;
957}
958
959
961{
962 static const GAL_LAYER_ID visible[] = {
969 // LAYER_MOD_TEXT_INVISIBLE, // Invisible text hidden by default
988 // LAYER_DRC_EXCLUSION, // DRC exclusions hidden by default
1000 };
1001
1002 static const GAL_SET saved( visible, arrayDim( visible ) );
1003 return saved;
1004}
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
Helper for storing and iterating over GAL_LAYER_IDs.
Definition: layer_ids.h:296
GAL_SET()
Definition: layer_ids.h:301
GAL_SET & set()
Definition: layer_ids.h:311
static GAL_SET DefaultVisible()
Definition: lset.cpp:960
std::vector< GAL_LAYER_ID > Seq() const
Definition: lset.cpp:946
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:493
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:532
static LSET ExternalCuMask()
Return a mask holding the Front and Bottom layers.
Definition: lset.cpp:801
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
LSEQ UIOrder() const
Definition: lset.cpp:922
static LSET AllBoardTechMask()
Return a mask holding board technical layers (no CU layer) on both side.
Definition: lset.cpp:848
static LSET AllLayersMask()
Definition: lset.cpp:808
static LSET UserDefinedLayers()
Return a mask with all of the allowable user defined layers.
Definition: lset.cpp:877
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
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
PCB_LAYER_ID ExtractLayer() const
Find the first set PCB_LAYER_ID.
Definition: lset.cpp:684
static LSET FrontBoardTechMask()
Return a mask holding technical layers used in a board fabrication (no CU layer) on front side.
Definition: lset.cpp:834
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:794
LSEQ SeqStackupBottom2Top() const
Return the sequence that is typical for a bottom-to-top stack-up.
Definition: lset.cpp:475
static LSET FrontAssembly()
Return a complete set of all top assembly layers which is all F_SilkS and F_Mask.
Definition: lset.cpp:705
LSEQ TechAndUserUIOrder() const
Returns the technical and user layers in the order shown in layer widget.
Definition: lset.cpp:261
static LSET UserMask()
Definition: lset.cpp:855
static LSET AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:841
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:733
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
static LSET SideSpecificMask()
Definition: lset.cpp:908
static LSET PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition: lset.cpp:870
LSEQ Seq() const
Return a LSEQ from this LSET in ascending PCB_LAYER_ID order.
Definition: lset.cpp:459
std::string FmtHex() const
Return a hex string showing contents of this LSEQ.
Definition: lset.cpp:321
static LSET ForbiddenFootprintLayers()
Layers which are not allowed within footprint definitions.
Definition: lset.cpp:915
LSEQ Technicals(LSET aSubToOmit=LSET()) const
Return a sequence of technical layers.
Definition: lset.cpp:212
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition: lset.cpp:82
std::string FmtBin() const
Return a binary string showing contents of this LSEQ.
Definition: lset.cpp:297
static LSET FrontTechMask()
Return a mask holding all technical layers (no CU layer) on front side.
Definition: lset.cpp:827
static LSET BackBoardTechMask()
Return a mask holding technical layers used in a board fabrication (no CU layer) on Back side.
Definition: lset.cpp:821
LSEQ Users() const
*_User layers.
Definition: lset.cpp:236
static LSET BackTechMask()
Return a mask holding all technical layers (no CU layer) on back side.
Definition: lset.cpp:815
static LSET BackAssembly()
Return a complete set of all bottom assembly layers which is all B_SilkS and B_Mask.
Definition: lset.cpp:719
static LSET FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
Definition: lset.cpp:895
static LSET BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
Definition: lset.cpp:902
LSET()
Create an empty (cleared) set.
Definition: layer_ids.h:548
std::bitset< PCB_LAYER_ID_COUNT > BASE_SET
Definition: layer_ids.h:522
#define MAX_CU_LAYERS
Definition: layer_ids.h:140
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:827
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
Definition: layer_ids.h:190
@ LAYER_GRID
Definition: layer_ids.h:205
@ GAL_LAYER_ID_START
Definition: layer_ids.h:191
@ LAYER_LOCKED_ITEM_SHADOW
shadow layer for locked items
Definition: layer_ids.h:239
@ LAYER_VIA_HOLEWALLS
Definition: layer_ids.h:234
@ LAYER_GRID_AXES
Definition: layer_ids.h:206
@ LAYER_CONFLICTS_SHADOW
shadow layer for items flagged conficting
Definition: layer_ids.h:241
@ LAYER_NON_PLATEDHOLES
handle color for not plated holes (holes, not pads)
Definition: layer_ids.h:197
@ LAYER_PAD_FR
smd pads, front layer
Definition: layer_ids.h:202
@ LAYER_DRAWINGSHEET
drawingsheet frame and titleblock
Definition: layer_ids.h:217
@ LAYER_DRAW_BITMAPS
to handle and draw images bitmaps
Definition: layer_ids.h:223
@ LAYER_MOD_TEXT
Definition: layer_ids.h:198
@ LAYER_PCB_BACKGROUND
PCB background color.
Definition: layer_ids.h:220
@ LAYER_ZONES
Control for copper zone opacity/visibility (color ignored)
Definition: layer_ids.h:231
@ LAYER_PADS
Meta control for all pads opacity/visibility (color ignored)
Definition: layer_ids.h:230
@ LAYER_DRC_WARNING
layer for drc markers with SEVERITY_WARNING
Definition: layer_ids.h:235
@ LAYER_PAD_PLATEDHOLES
to draw pad holes (plated)
Definition: layer_ids.h:214
@ GAL_LAYER_ID_END
Definition: layer_ids.h:260
@ LAYER_GP_OVERLAY
general purpose overlay
Definition: layer_ids.h:218
@ LAYER_TRACKS
Definition: layer_ids.h:212
@ LAYER_CURSOR
PCB cursor.
Definition: layer_ids.h:221
@ LAYER_AUX_ITEMS
Auxiliary items (guides, rule, etc)
Definition: layer_ids.h:222
@ LAYER_RATSNEST
Definition: layer_ids.h:204
@ LAYER_MOD_FR
show footprints on front
Definition: layer_ids.h:208
@ LAYER_ANCHOR
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:201
@ LAYER_PAD_BK
smd pads, back layer
Definition: layer_ids.h:203
@ LAYER_MOD_VALUES
show footprints values (when texts are visible)
Definition: layer_ids.h:210
@ LAYER_PADS_TH
multilayer pads, usually with holes
Definition: layer_ids.h:213
@ LAYER_VIA_HOLES
to draw via holes (pad holes do not use this layer)
Definition: layer_ids.h:215
@ LAYER_VIA_MICROVIA
to draw micro vias
Definition: layer_ids.h:194
@ LAYER_SELECT_OVERLAY
currently selected items overlay
Definition: layer_ids.h:219
@ LAYER_VIA_THROUGH
to draw usual through hole vias
Definition: layer_ids.h:196
@ LAYER_DRC_ERROR
layer for drc markers with SEVERITY_ERROR
Definition: layer_ids.h:216
@ LAYER_VIAS
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:193
@ LAYER_MOD_BK
show footprints on back
Definition: layer_ids.h:209
@ LAYER_MOD_REFERENCES
show footprints references (when texts are visible)
Definition: layer_ids.h:211
@ LAYER_VIA_BBLIND
to draw blind/buried vias
Definition: layer_ids.h:195
@ LAYER_PAD_HOLEWALLS
Definition: layer_ids.h:233
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ In22_Cu
Definition: layer_ids.h:86
@ In11_Cu
Definition: layer_ids.h:75
@ In29_Cu
Definition: layer_ids.h:93
@ In30_Cu
Definition: layer_ids.h:94
@ User_8
Definition: layer_ids.h:130
@ F_CrtYd
Definition: layer_ids.h:117
@ In17_Cu
Definition: layer_ids.h:81
@ B_Adhes
Definition: layer_ids.h:97
@ Edge_Cuts
Definition: layer_ids.h:113
@ Dwgs_User
Definition: layer_ids.h:109
@ F_Paste
Definition: layer_ids.h:101
@ In9_Cu
Definition: layer_ids.h:73
@ Cmts_User
Definition: layer_ids.h:110
@ User_6
Definition: layer_ids.h:128
@ User_7
Definition: layer_ids.h:129
@ In19_Cu
Definition: layer_ids.h:83
@ In7_Cu
Definition: layer_ids.h:71
@ In28_Cu
Definition: layer_ids.h:92
@ In26_Cu
Definition: layer_ids.h:90
@ F_Adhes
Definition: layer_ids.h:98
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ User_5
Definition: layer_ids.h:127
@ Eco1_User
Definition: layer_ids.h:111
@ F_Mask
Definition: layer_ids.h:107
@ In21_Cu
Definition: layer_ids.h:85
@ In23_Cu
Definition: layer_ids.h:87
@ B_Paste
Definition: layer_ids.h:100
@ In15_Cu
Definition: layer_ids.h:79
@ In2_Cu
Definition: layer_ids.h:66
@ User_9
Definition: layer_ids.h:131
@ UNSELECTED_LAYER
Definition: layer_ids.h:61
@ F_Fab
Definition: layer_ids.h:120
@ In10_Cu
Definition: layer_ids.h:74
@ Margin
Definition: layer_ids.h:114
@ F_SilkS
Definition: layer_ids.h:104
@ In4_Cu
Definition: layer_ids.h:68
@ B_CrtYd
Definition: layer_ids.h:116
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
@ Eco2_User
Definition: layer_ids.h:112
@ In16_Cu
Definition: layer_ids.h:80
@ In24_Cu
Definition: layer_ids.h:88
@ In1_Cu
Definition: layer_ids.h:65
@ Rescue
Definition: layer_ids.h:133
@ User_3
Definition: layer_ids.h:125
@ User_1
Definition: layer_ids.h:123
@ B_SilkS
Definition: layer_ids.h:103
@ In13_Cu
Definition: layer_ids.h:77
@ User_4
Definition: layer_ids.h:126
@ In8_Cu
Definition: layer_ids.h:72
@ In14_Cu
Definition: layer_ids.h:78
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:137
@ User_2
Definition: layer_ids.h:124
@ In12_Cu
Definition: layer_ids.h:76
@ In27_Cu
Definition: layer_ids.h:91
@ In6_Cu
Definition: layer_ids.h:70
@ In5_Cu
Definition: layer_ids.h:69
@ In3_Cu
Definition: layer_ids.h:67
@ In20_Cu
Definition: layer_ids.h:84
@ F_Cu
Definition: layer_ids.h:64
@ In18_Cu
Definition: layer_ids.h:82
@ In25_Cu
Definition: layer_ids.h:89
@ B_Fab
Definition: layer_ids.h:119
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
Definition: lset.cpp:590
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:932
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:544
This file contains miscellaneous commonly used macros and functions.
constexpr T Clamp(const T &lower, const T &value, const T &upper)
Limit value within the range lower <= value <= upper.
Definition: util.h:64