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