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-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
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 // bottom-to-top stack-up layers
485 // Note that the bottom technical layers are flipped so that when plotting a bottom-side view,
486 // they appear in the correct sequence.
487 static const PCB_LAYER_ID sequence[] = {
488 B_Cu,
489 B_Mask,
490 B_Paste,
491 B_SilkS,
492 B_Adhes,
493 B_CrtYd,
494 B_Fab,
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 User_1,
537 User_2,
538 User_3,
539 User_4,
540 User_5,
541 User_6,
542 User_7,
543 User_8,
544 User_9,
545 Margin,
546 Edge_Cuts,
547 };
548
549 return Seq( sequence, arrayDim( sequence ) );
550}
551
552
553PCB_LAYER_ID FlipLayer( PCB_LAYER_ID aLayerId, int aCopperLayersCount )
554{
555 switch( aLayerId )
556 {
557 case B_Cu: return F_Cu;
558 case F_Cu: return B_Cu;
559
560 case B_SilkS: return F_SilkS;
561 case F_SilkS: return B_SilkS;
562
563 case B_Adhes: return F_Adhes;
564 case F_Adhes: return B_Adhes;
565
566 case B_Mask: return F_Mask;
567 case F_Mask: return B_Mask;
568
569 case B_Paste: return F_Paste;
570 case F_Paste: return B_Paste;
571
572 case B_CrtYd: return F_CrtYd;
573 case F_CrtYd: return B_CrtYd;
574
575 case B_Fab: return F_Fab;
576 case F_Fab: return B_Fab;
577
578 default: // change internal layer if aCopperLayersCount is >= 4
579 if( IsCopperLayer( aLayerId ) && aCopperLayersCount >= 4 )
580 {
581 // internal copper layers count is aCopperLayersCount-2
582 PCB_LAYER_ID fliplayer = PCB_LAYER_ID(aCopperLayersCount - 2 - ( aLayerId - In1_Cu ) );
583 // Ensure fliplayer has a value which does not crash Pcbnew:
584 if( fliplayer < F_Cu )
585 fliplayer = F_Cu;
586
587 if( fliplayer > B_Cu )
588 fliplayer = B_Cu;
589
590 return fliplayer;
591 }
592
593 // No change for the other layers
594 return aLayerId;
595 }
596}
597
598
599LSET FlipLayerMask( LSET aMask, int aCopperLayersCount )
600{
601 // layers on physical outside of a board:
602 const static LSET and_mask( 16, // !! update count
603 B_Cu, F_Cu,
606 B_Mask, F_Mask,
610 B_Fab, F_Fab
611 );
612
613 LSET newMask = aMask & ~and_mask;
614
615 if( aMask[B_Cu] )
616 newMask.set( F_Cu );
617
618 if( aMask[F_Cu] )
619 newMask.set( B_Cu );
620
621 if( aMask[B_SilkS] )
622 newMask.set( F_SilkS );
623
624 if( aMask[F_SilkS] )
625 newMask.set( B_SilkS );
626
627 if( aMask[B_Adhes] )
628 newMask.set( F_Adhes );
629
630 if( aMask[F_Adhes] )
631 newMask.set( B_Adhes );
632
633 if( aMask[B_Mask] )
634 newMask.set( F_Mask );
635
636 if( aMask[F_Mask] )
637 newMask.set( B_Mask );
638
639 if( aMask[B_Paste] )
640 newMask.set( F_Paste );
641
642 if( aMask[F_Paste] )
643 newMask.set( B_Paste );
644
645 if( aMask[B_Adhes] )
646 newMask.set( F_Adhes );
647
648 if( aMask[F_Adhes] )
649 newMask.set( B_Adhes );
650
651 if( aMask[B_CrtYd] )
652 newMask.set( F_CrtYd );
653
654 if( aMask[F_CrtYd] )
655 newMask.set( B_CrtYd );
656
657 if( aMask[B_Fab] )
658 newMask.set( F_Fab );
659
660 if( aMask[F_Fab] )
661 newMask.set( B_Fab );
662
663 if( aCopperLayersCount >= 4 ) // Internal layers exist
664 {
665 LSET internalMask = aMask & LSET::InternalCuMask();
666
667 if( internalMask != LSET::InternalCuMask() )
668 {
669 // the mask does not include all internal layers. Therefore
670 // the flipped mask for internal copper layers must be built
671 int innerLayerCnt = aCopperLayersCount -2;
672
673 // the flipped mask is the innerLayerCnt bits rewritten in reverse order
674 // ( bits innerLayerCnt to 1 rewritten in bits 1 to innerLayerCnt )
675 for( int ii = 0; ii < innerLayerCnt; ii++ )
676 {
677 if( internalMask[innerLayerCnt - ii] )
678 {
679 newMask.set( ii + In1_Cu );
680 }
681 else
682 {
683 newMask.reset( ii + In1_Cu );
684 }
685 }
686 }
687 }
688
689 return newMask;
690}
691
692
694{
695 unsigned set_count = count();
696
697 if( !set_count )
698 return UNSELECTED_LAYER;
699 else if( set_count > 1 )
700 return UNDEFINED_LAYER;
701
702 for( unsigned i=0; i < size(); ++i )
703 {
704 if( test( i ) )
705 return PCB_LAYER_ID( i );
706 }
707
708 wxASSERT( 0 ); // set_count was verified as 1 above, what did you break?
709
710 return UNDEFINED_LAYER;
711}
712
713
715{
716 static const PCB_LAYER_ID front_assembly[] = {
717 F_SilkS,
718 F_Mask,
719 F_Fab,
720 F_CrtYd
721 };
722
723 static const LSET saved( front_assembly, arrayDim( front_assembly ) );
724 return saved;
725}
726
727
729{
730 static const PCB_LAYER_ID back_assembly[] = {
731 B_SilkS,
732 B_Mask,
733 B_Fab,
734 B_CrtYd
735 };
736
737 static const LSET saved( back_assembly, arrayDim( back_assembly ) );
738 return saved;
739}
740
741
743{
744 static const PCB_LAYER_ID cu_internals[] = {
745 In1_Cu,
746 In2_Cu,
747 In3_Cu,
748 In4_Cu,
749 In5_Cu,
750 In6_Cu,
751 In7_Cu,
752 In8_Cu,
753 In9_Cu,
754 In10_Cu,
755 In11_Cu,
756 In12_Cu,
757 In13_Cu,
758 In14_Cu,
759 In15_Cu,
760 In16_Cu,
761 In17_Cu,
762 In18_Cu,
763 In19_Cu,
764 In20_Cu,
765 In21_Cu,
766 In22_Cu,
767 In23_Cu,
768 In24_Cu,
769 In25_Cu,
770 In26_Cu,
771 In27_Cu,
772 In28_Cu,
773 In29_Cu,
774 In30_Cu,
775 };
776
777 static const LSET saved( cu_internals, arrayDim( cu_internals ) );
778 return saved;
779}
780
781
782LSET LSET::AllCuMask( int aCuLayerCount )
783{
784 // retain all in static as the full set, which is a common case.
785 static const LSET all = InternalCuMask().set( F_Cu ).set( B_Cu );
786
787 if( aCuLayerCount == MAX_CU_LAYERS )
788 return all;
789
790 // subtract out some Cu layers not wanted in the mask.
791 LSET ret = all;
792 int clear_count = MAX_CU_LAYERS - aCuLayerCount;
793
794 clear_count = Clamp( 0, clear_count, MAX_CU_LAYERS - 2 );
795
796 for( int elem = In30_Cu; clear_count; --elem, --clear_count )
797 ret.set( elem, false );
798
799 return ret;
800}
801
802
804{
805 static const LSET saved = LSET().set() & ~AllCuMask();
806 return saved;
807}
808
809
811{
812 static const LSET saved( 2, F_Cu, B_Cu );
813 return saved;
814}
815
816
818{
819 static const LSET saved = LSET().set();
820 return saved;
821}
822
823
825{
826 static const LSET saved( 6, B_SilkS, B_Mask, B_Adhes, B_Paste, B_CrtYd, B_Fab );
827 return saved;
828}
829
831{
832 static const LSET saved( 4, B_SilkS, B_Mask, B_Adhes, B_Paste );
833 return saved;
834}
835
837{
838 static const LSET saved( 6, F_SilkS, F_Mask, F_Adhes, F_Paste, F_CrtYd, F_Fab );
839 return saved;
840}
841
842
844{
845 static const LSET saved( 4, F_SilkS, F_Mask, F_Adhes, F_Paste );
846 return saved;
847}
848
849
851{
852 static const LSET saved = BackTechMask() | FrontTechMask();
853 return saved;
854}
855
856
858{
859 static const LSET saved = BackBoardTechMask() | FrontBoardTechMask();
860 return saved;
861}
862
863
865{
866 static const LSET saved( 6,
867 Dwgs_User,
868 Cmts_User,
869 Eco1_User,
870 Eco2_User,
871 Edge_Cuts,
872 Margin
873 );
874
875 return saved;
876}
877
878
880{
881 static const LSET saved = AllBoardTechMask() | AllCuMask();
882 return saved;
883}
884
885
887{
888 static const LSET saved( 9,
889 User_1,
890 User_2,
891 User_3,
892 User_4,
893 User_5,
894 User_6,
895 User_7,
896 User_8,
897 User_9
898 );
899
900 return saved;
901}
902
903
905{
906 static const LSET saved = FrontTechMask().set( F_Cu );
907 return saved;
908}
909
910
912{
913 static const LSET saved = BackTechMask().set( B_Cu );
914 return saved;
915}
916
918{
919 static const LSET saved = BackTechMask() | FrontTechMask() | AllCuMask();
920 return saved;
921}
922
923
925{
926 static const LSET saved = InternalCuMask();
927 return saved;
928}
929
930
932{
933 LSEQ order = CuStack();
934 LSEQ techuser = TechAndUserUIOrder();
935 order.insert( order.end(), techuser.begin(), techuser.end() );
936
937 return order;
938}
939
940
942{
943 wxASSERT( aLayer < GAL_LAYER_ID_END );
944 return PCB_LAYER_ID( aLayer );
945}
946
947
948GAL_SET::GAL_SET( const GAL_LAYER_ID* aArray, unsigned aCount ) : GAL_SET()
949{
950 for( unsigned i = 0; i < aCount; ++i )
951 set( aArray[i] );
952}
953
954
955std::vector<GAL_LAYER_ID> GAL_SET::Seq() const
956{
957 std::vector<GAL_LAYER_ID> ret;
958
959 for( size_t i = 0; i < size(); ++i )
960 {
961 if( test( i ) )
962 ret.push_back( static_cast<GAL_LAYER_ID>( i + GAL_LAYER_ID_START ) );
963 }
964
965 return ret;
966}
967
968
970{
971 static const GAL_LAYER_ID visible[] = {
976 // LAYER_HIDDEN_TEXT, // Invisible text hidden by default
997 // LAYER_DRC_EXCLUSION, // DRC exclusions hidden by default
1005 LAYER_PADS,
1009 };
1010
1011 static const GAL_SET saved( visible, arrayDim( visible ) );
1012 return saved;
1013}
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:300
GAL_SET()
Definition: layer_ids.h:306
GAL_SET & set()
Definition: layer_ids.h:316
static GAL_SET DefaultVisible()
Definition: lset.cpp:969
std::vector< GAL_LAYER_ID > Seq() const
Definition: lset.cpp:955
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:513
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:556
static LSET ExternalCuMask()
Return a mask holding the Front and Bottom layers.
Definition: lset.cpp:810
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:931
static LSET AllBoardTechMask()
Return a mask holding board technical layers (no CU layer) on both side.
Definition: lset.cpp:857
static LSET AllLayersMask()
Definition: lset.cpp:817
static LSET UserDefinedLayers()
Return a mask with all of the allowable user defined layers.
Definition: lset.cpp:886
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:693
static LSET FrontBoardTechMask()
Return a mask holding technical layers used in a board fabrication (no CU layer) on front side.
Definition: lset.cpp:843
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:803
LSEQ SeqStackupBottom2Top() const
Return the sequence that is typical for a bottom-to-top stack-up.
Definition: lset.cpp:482
static LSET FrontAssembly()
Return a complete set of all top assembly layers which is all F_SilkS and F_Mask.
Definition: lset.cpp:714
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:864
static LSET AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition: lset.cpp:850
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:742
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:782
static LSET SideSpecificMask()
Definition: lset.cpp:917
static LSET PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition: lset.cpp:879
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:924
LSEQ Technicals(LSET aSubToOmit=LSET()) const
Return a sequence of technical layers.
Definition: lset.cpp:219
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:836
static LSET BackBoardTechMask()
Return a mask holding technical layers used in a board fabrication (no CU layer) on Back side.
Definition: lset.cpp:830
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:824
static LSET BackAssembly()
Return a complete set of all bottom assembly layers which is all B_SilkS and B_Mask.
Definition: lset.cpp:728
static LSET FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
Definition: lset.cpp:904
static LSET BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
Definition: lset.cpp:911
LSET()
Create an empty (cleared) set.
Definition: layer_ids.h:572
std::bitset< PCB_LAYER_ID_COUNT > BASE_SET
Definition: layer_ids.h:546
#define MAX_CU_LAYERS
Definition: layer_ids.h:141
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:853
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
Definition: layer_ids.h:191
@ LAYER_GRID
Definition: layer_ids.h:206
@ GAL_LAYER_ID_START
Definition: layer_ids.h:192
@ LAYER_LOCKED_ITEM_SHADOW
shadow layer for locked items
Definition: layer_ids.h:240
@ LAYER_VIA_HOLEWALLS
Definition: layer_ids.h:235
@ LAYER_GRID_AXES
Definition: layer_ids.h:207
@ LAYER_CONFLICTS_SHADOW
shadow layer for items flagged conficting
Definition: layer_ids.h:242
@ LAYER_FOOTPRINTS_FR
show footprints on front
Definition: layer_ids.h:209
@ LAYER_NON_PLATEDHOLES
handle color for not plated holes (holes, not pads)
Definition: layer_ids.h:198
@ LAYER_DRAWINGSHEET
drawingsheet frame and titleblock
Definition: layer_ids.h:218
@ LAYER_DRAW_BITMAPS
to handle and draw images bitmaps
Definition: layer_ids.h:224
@ LAYER_FP_REFERENCES
show footprints references (when texts are visible)
Definition: layer_ids.h:212
@ LAYER_PCB_BACKGROUND
PCB background color.
Definition: layer_ids.h:221
@ LAYER_ZONES
Control for copper zone opacity/visibility (color ignored)
Definition: layer_ids.h:232
@ LAYER_PADS
Meta control for all pads opacity/visibility (color ignored)
Definition: layer_ids.h:231
@ LAYER_DRC_WARNING
layer for drc markers with SEVERITY_WARNING
Definition: layer_ids.h:236
@ LAYER_PAD_PLATEDHOLES
to draw pad holes (plated)
Definition: layer_ids.h:215
@ GAL_LAYER_ID_END
Definition: layer_ids.h:261
@ LAYER_GP_OVERLAY
general purpose overlay
Definition: layer_ids.h:219
@ LAYER_TRACKS
Definition: layer_ids.h:213
@ LAYER_CURSOR
PCB cursor.
Definition: layer_ids.h:222
@ LAYER_AUX_ITEMS
Auxiliary items (guides, rule, etc)
Definition: layer_ids.h:223
@ LAYER_RATSNEST
Definition: layer_ids.h:205
@ LAYER_FP_TEXT
Definition: layer_ids.h:199
@ LAYER_FOOTPRINTS_BK
show footprints on back
Definition: layer_ids.h:210
@ LAYER_ANCHOR
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:202
@ LAYER_PADS_SMD_BK
smd pads, back layer
Definition: layer_ids.h:204
@ LAYER_PADS_TH
multilayer pads, usually with holes
Definition: layer_ids.h:214
@ LAYER_PADS_SMD_FR
smd pads, front layer
Definition: layer_ids.h:203
@ LAYER_VIA_HOLES
to draw via holes (pad holes do not use this layer)
Definition: layer_ids.h:216
@ LAYER_FP_VALUES
show footprints values (when texts are visible)
Definition: layer_ids.h:211
@ LAYER_VIA_MICROVIA
to draw micro vias
Definition: layer_ids.h:195
@ LAYER_SELECT_OVERLAY
currently selected items overlay
Definition: layer_ids.h:220
@ LAYER_VIA_THROUGH
to draw usual through hole vias
Definition: layer_ids.h:197
@ LAYER_DRC_ERROR
layer for drc markers with SEVERITY_ERROR
Definition: layer_ids.h:217
@ LAYER_VIAS
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:194
@ LAYER_VIA_BBLIND
to draw blind/buried vias
Definition: layer_ids.h:196
@ LAYER_PAD_HOLEWALLS
Definition: layer_ids.h:234
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ In22_Cu
Definition: layer_ids.h:87
@ In11_Cu
Definition: layer_ids.h:76
@ In29_Cu
Definition: layer_ids.h:94
@ In30_Cu
Definition: layer_ids.h:95
@ User_8
Definition: layer_ids.h:131
@ F_CrtYd
Definition: layer_ids.h:118
@ In17_Cu
Definition: layer_ids.h:82
@ B_Adhes
Definition: layer_ids.h:98
@ Edge_Cuts
Definition: layer_ids.h:114
@ Dwgs_User
Definition: layer_ids.h:110
@ F_Paste
Definition: layer_ids.h:102
@ In9_Cu
Definition: layer_ids.h:74
@ Cmts_User
Definition: layer_ids.h:111
@ User_6
Definition: layer_ids.h:129
@ User_7
Definition: layer_ids.h:130
@ In19_Cu
Definition: layer_ids.h:84
@ In7_Cu
Definition: layer_ids.h:72
@ In28_Cu
Definition: layer_ids.h:93
@ In26_Cu
Definition: layer_ids.h:91
@ F_Adhes
Definition: layer_ids.h:99
@ B_Mask
Definition: layer_ids.h:107
@ B_Cu
Definition: layer_ids.h:96
@ User_5
Definition: layer_ids.h:128
@ Eco1_User
Definition: layer_ids.h:112
@ F_Mask
Definition: layer_ids.h:108
@ In21_Cu
Definition: layer_ids.h:86
@ In23_Cu
Definition: layer_ids.h:88
@ B_Paste
Definition: layer_ids.h:101
@ In15_Cu
Definition: layer_ids.h:80
@ In2_Cu
Definition: layer_ids.h:67
@ User_9
Definition: layer_ids.h:132
@ UNSELECTED_LAYER
Definition: layer_ids.h:62
@ F_Fab
Definition: layer_ids.h:121
@ In10_Cu
Definition: layer_ids.h:75
@ Margin
Definition: layer_ids.h:115
@ F_SilkS
Definition: layer_ids.h:105
@ In4_Cu
Definition: layer_ids.h:69
@ B_CrtYd
Definition: layer_ids.h:117
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ Eco2_User
Definition: layer_ids.h:113
@ In16_Cu
Definition: layer_ids.h:81
@ In24_Cu
Definition: layer_ids.h:89
@ In1_Cu
Definition: layer_ids.h:66
@ Rescue
Definition: layer_ids.h:134
@ User_3
Definition: layer_ids.h:126
@ User_1
Definition: layer_ids.h:124
@ B_SilkS
Definition: layer_ids.h:104
@ In13_Cu
Definition: layer_ids.h:78
@ User_4
Definition: layer_ids.h:127
@ In8_Cu
Definition: layer_ids.h:73
@ In14_Cu
Definition: layer_ids.h:79
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:138
@ User_2
Definition: layer_ids.h:125
@ In12_Cu
Definition: layer_ids.h:77
@ In27_Cu
Definition: layer_ids.h:92
@ In6_Cu
Definition: layer_ids.h:71
@ In5_Cu
Definition: layer_ids.h:70
@ In3_Cu
Definition: layer_ids.h:68
@ In20_Cu
Definition: layer_ids.h:85
@ F_Cu
Definition: layer_ids.h:65
@ In18_Cu
Definition: layer_ids.h:83
@ In25_Cu
Definition: layer_ids.h:90
@ B_Fab
Definition: layer_ids.h:120
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
Definition: lset.cpp:599
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:941
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:553
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