You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							818 lines
						
					
					
						
							19 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							818 lines
						
					
					
						
							19 KiB
						
					
					
				| /* | |
|  * This program source code file is part of KiCad, a free EDA CAD application. | |
|  * | |
|  * Copyright (C) 2014 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> | |
|  * Copyright (C) 2014-2017 KiCad Developers, see AUTHORS.txt for contributors. | |
|  * | |
|  * This program is free software; you can redistribute it and/or | |
|  * modify it under the terms of the GNU General Public License | |
|  * as published by the Free Software Foundation; either version 2 | |
|  * of the License, or (at your option) any later version. | |
|  * | |
|  * This program is distributed in the hope that it will be useful, | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | |
|  * GNU General Public License for more details. | |
|  * | |
|  * You should have received a copy of the GNU General Public License | |
|  * along with this program; if not, you may find one here: | |
|  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html | |
|  * or you may search the http://www.gnu.org website for the version 2 license, | |
|  * or you may write to the Free Software Foundation, Inc., | |
|  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA | |
|  */ | |
| 
 | |
| 
 | |
| #include <stdarg.h> | |
| #include <assert.h> | |
|  | |
| #include <layers_id_colors_and_visibility.h> | |
| #include <class_board.h> | |
|  | |
| 
 | |
| LSET::LSET( const PCB_LAYER_ID* aArray, unsigned aCount ) : | |
|     BASE_SET() | |
| { | |
|     for( unsigned i=0; i<aCount; ++i ) | |
|         set( aArray[i] ); | |
| } | |
| 
 | |
| 
 | |
| LSET::LSET( unsigned aIdCount, int aFirst, ... ) : | |
|     BASE_SET() | |
| { | |
|     // The constructor, without the mandatory aFirst argument, could have been confused | |
|     // by the compiler with the LSET( PCB_LAYER_ID ).  With aFirst, that ambiguity is not | |
|     // present.  Therefore aIdCount must always be >=1. | |
|     wxASSERT_MSG( aIdCount > 0, wxT( "aIdCount must be >= 1" ) ); | |
| 
 | |
|     set( aFirst ); | |
| 
 | |
|     if( --aIdCount ) | |
|     { | |
|         va_list ap; | |
| 
 | |
|         va_start( ap, aFirst ); | |
| 
 | |
|         for( unsigned i=0;  i<aIdCount;  ++i ) | |
|         { | |
|             PCB_LAYER_ID id = (PCB_LAYER_ID) va_arg( ap, int ); | |
| 
 | |
|             // printf( "%s: id:%d PCB_LAYER_ID_COUNT:%d\n", __func__, id, PCB_LAYER_ID_COUNT ); | |
|  | |
|             assert( unsigned( id ) < PCB_LAYER_ID_COUNT ); | |
| 
 | |
|             set( id ); | |
|         } | |
| 
 | |
|         va_end( ap ); | |
|     } | |
| } | |
| 
 | |
| 
 | |
| const wxChar* LSET::Name( PCB_LAYER_ID aLayerId ) | |
| { | |
|     const wxChar* txt; | |
| 
 | |
|     // using a switch to explicitly show the mapping more clearly | |
|     switch( aLayerId ) | |
|     { | |
|     case F_Cu:              txt = wxT( "F.Cu" );            break; | |
|     case In1_Cu:            txt = wxT( "In1.Cu" );          break; | |
|     case In2_Cu:            txt = wxT( "In2.Cu" );          break; | |
|     case In3_Cu:            txt = wxT( "In3.Cu" );          break; | |
|     case In4_Cu:            txt = wxT( "In4.Cu" );          break; | |
|     case In5_Cu:            txt = wxT( "In5.Cu" );          break; | |
|     case In6_Cu:            txt = wxT( "In6.Cu" );          break; | |
|     case In7_Cu:            txt = wxT( "In7.Cu" );          break; | |
|     case In8_Cu:            txt = wxT( "In8.Cu" );          break; | |
|     case In9_Cu:            txt = wxT( "In9.Cu" );          break; | |
|     case In10_Cu:           txt = wxT( "In10.Cu" );         break; | |
|     case In11_Cu:           txt = wxT( "In11.Cu" );         break; | |
|     case In12_Cu:           txt = wxT( "In12.Cu" );         break; | |
|     case In13_Cu:           txt = wxT( "In13.Cu" );         break; | |
|     case In14_Cu:           txt = wxT( "In14.Cu" );         break; | |
|     case In15_Cu:           txt = wxT( "In15.Cu" );         break; | |
|     case In16_Cu:           txt = wxT( "In16.Cu" );         break; | |
|     case In17_Cu:           txt = wxT( "In17.Cu" );         break; | |
|     case In18_Cu:           txt = wxT( "In18.Cu" );         break; | |
|     case In19_Cu:           txt = wxT( "In19.Cu" );         break; | |
|     case In20_Cu:           txt = wxT( "In20.Cu" );         break; | |
|     case In21_Cu:           txt = wxT( "In21.Cu" );         break; | |
|     case In22_Cu:           txt = wxT( "In22.Cu" );         break; | |
|     case In23_Cu:           txt = wxT( "In23.Cu" );         break; | |
|     case In24_Cu:           txt = wxT( "In24.Cu" );         break; | |
|     case In25_Cu:           txt = wxT( "In25.Cu" );         break; | |
|     case In26_Cu:           txt = wxT( "In26.Cu" );         break; | |
|     case In27_Cu:           txt = wxT( "In27.Cu" );         break; | |
|     case In28_Cu:           txt = wxT( "In28.Cu" );         break; | |
|     case In29_Cu:           txt = wxT( "In29.Cu" );         break; | |
|     case In30_Cu:           txt = wxT( "In30.Cu" );         break; | |
|     case B_Cu:              txt = wxT( "B.Cu" );            break; | |
| 
 | |
|     // Technicals | |
|     case B_Adhes:           txt = wxT( "B.Adhes" );         break; | |
|     case F_Adhes:           txt = wxT( "F.Adhes" );         break; | |
|     case B_Paste:           txt = wxT( "B.Paste" );         break; | |
|     case F_Paste:           txt = wxT( "F.Paste" );         break; | |
|     case B_SilkS:           txt = wxT( "B.SilkS" );         break; | |
|     case F_SilkS:           txt = wxT( "F.SilkS" );         break; | |
|     case B_Mask:            txt = wxT( "B.Mask" );          break; | |
|     case F_Mask:            txt = wxT( "F.Mask" );          break; | |
| 
 | |
|     // Users | |
|     case Dwgs_User:         txt = wxT( "Dwgs.User" );       break; | |
|     case Cmts_User:         txt = wxT( "Cmts.User" );       break; | |
|     case Eco1_User:         txt = wxT( "Eco1.User" );       break; | |
|     case Eco2_User:         txt = wxT( "Eco2.User" );       break; | |
|     case Edge_Cuts:         txt = wxT( "Edge.Cuts" );       break; | |
|     case Margin:            txt = wxT( "Margin" );          break; | |
| 
 | |
|     // Footprint | |
|     case F_CrtYd:           txt = wxT( "F.CrtYd" );         break; | |
|     case B_CrtYd:           txt = wxT( "B.CrtYd" );         break; | |
|     case F_Fab:             txt = wxT( "F.Fab" );           break; | |
|     case B_Fab:             txt = wxT( "B.Fab" );           break; | |
| 
 | |
|     // Rescue | |
|     case Rescue:            txt = wxT( "Rescue" );          break; | |
| 
 | |
|     default: | |
|         std::cout << aLayerId << std::endl; | |
|         wxASSERT_MSG( 0, wxT( "aLayerId out of range" ) ); | |
|                             txt = wxT( "BAD INDEX!" );      break; | |
|     } | |
| 
 | |
|     return txt; | |
| } | |
| 
 | |
| 
 | |
| LSEQ LSET::CuStack() const | |
| { | |
|     // desired sequence | |
|     static const PCB_LAYER_ID sequence[] = { | |
|         F_Cu, | |
|         In1_Cu, | |
|         In2_Cu, | |
|         In3_Cu, | |
|         In4_Cu, | |
|         In5_Cu, | |
|         In6_Cu, | |
|         In7_Cu, | |
|         In8_Cu, | |
|         In9_Cu, | |
|         In10_Cu, | |
|         In11_Cu, | |
|         In12_Cu, | |
|         In13_Cu, | |
|         In14_Cu, | |
|         In15_Cu, | |
|         In16_Cu, | |
|         In17_Cu, | |
|         In18_Cu, | |
|         In19_Cu, | |
|         In20_Cu, | |
|         In21_Cu, | |
|         In22_Cu, | |
|         In23_Cu, | |
|         In24_Cu, | |
|         In25_Cu, | |
|         In26_Cu, | |
|         In27_Cu, | |
|         In28_Cu, | |
|         In29_Cu, | |
|         In30_Cu, | |
|         B_Cu,           // 31 | |
|     }; | |
| 
 | |
|     return Seq( sequence, arrayDim( sequence ) ); | |
| } | |
| 
 | |
| 
 | |
| LSEQ LSET::Technicals( LSET aSetToOmit ) const | |
| { | |
|     // desired sequence | |
|     static const PCB_LAYER_ID sequence[] = { | |
|         F_Adhes, | |
|         B_Adhes, | |
|         F_Paste, | |
|         B_Paste, | |
|         F_SilkS, | |
|         B_SilkS, | |
|         F_Mask, | |
|         B_Mask, | |
|         F_CrtYd, | |
|         B_CrtYd, | |
|         F_Fab, | |
|         B_Fab, | |
|     }; | |
| 
 | |
|     LSET subset = ~aSetToOmit & *this; | |
| 
 | |
|     return subset.Seq( sequence, arrayDim( sequence ) ); | |
| } | |
| 
 | |
| 
 | |
| LSEQ LSET::Users() const | |
| { | |
|     // desired | |
|     static const PCB_LAYER_ID sequence[] = { | |
|         Dwgs_User, | |
|         Cmts_User, | |
|         Eco1_User, | |
|         Eco2_User, | |
|         Edge_Cuts, | |
|         Margin, | |
|    }; | |
| 
 | |
|    return Seq( sequence, arrayDim( sequence ) ); | |
| } | |
| 
 | |
| 
 | |
| LSEQ LSET::TechAndUserUIOrder() const | |
| { | |
|     static const PCB_LAYER_ID sequence[] = { | |
|         F_Adhes, | |
|         B_Adhes, | |
|         F_Paste, | |
|         B_Paste, | |
|         F_SilkS, | |
|         B_SilkS, | |
|         F_Mask, | |
|         B_Mask, | |
|         Dwgs_User, | |
|         Cmts_User, | |
|         Eco1_User, | |
|         Eco2_User, | |
|         Edge_Cuts, | |
|         Margin, | |
|         F_CrtYd, | |
|         B_CrtYd, | |
|         F_Fab, | |
|         B_Fab, | |
|    }; | |
| 
 | |
|    return Seq( sequence, arrayDim( sequence ) ); | |
| } | |
| 
 | |
| 
 | |
| std::string LSET::FmtBin() const | |
| { | |
|     std::string ret; | |
| 
 | |
|     int     bit_count = size(); | |
| 
 | |
|     for( int bit=0;  bit<bit_count;  ++bit ) | |
|     { | |
|         if( bit ) | |
|         { | |
|             if( !( bit % 8 ) ) | |
|                 ret += '|'; | |
|             else if( !( bit % 4 ) ) | |
|                 ret += '_'; | |
|         } | |
| 
 | |
|         ret += (*this)[bit] ? '1' :  '0'; | |
|     } | |
| 
 | |
|     // reverse of string | |
|     return std::string( ret.rbegin(), ret.rend() ); | |
| } | |
| 
 | |
| 
 | |
| std::string LSET::FmtHex() const | |
| { | |
|     std::string ret; | |
| 
 | |
|     static const char hex[] = "0123456789abcdef"; | |
| 
 | |
|     int     nibble_count = ( size() + 3 ) / 4; | |
| 
 | |
|     for( int nibble=0;  nibble<nibble_count;  ++nibble ) | |
|     { | |
|         unsigned ndx = 0; | |
| 
 | |
|         // test 4 consecutive bits and set ndx to 0-15: | |
|         for( int nibble_bit=0;  nibble_bit<4;  ++nibble_bit ) | |
|         { | |
|             if( (*this)[nibble_bit + nibble*4] ) | |
|                 ndx |= (1 << nibble_bit); | |
|         } | |
| 
 | |
|         if( nibble && !( nibble % 8 ) ) | |
|             ret += '_'; | |
| 
 | |
|         assert( ndx < arrayDim( hex ) ); | |
| 
 | |
|         ret += hex[ndx]; | |
|     } | |
| 
 | |
|     // reverse of string | |
|     return std::string( ret.rbegin(), ret.rend() ); | |
| } | |
| 
 | |
| 
 | |
| int LSET::ParseHex( const char* aStart, int aCount ) | |
| { | |
|     LSET tmp; | |
| 
 | |
|     const char* rstart = aStart + aCount - 1; | |
|     const char* rend   = aStart - 1; | |
| 
 | |
|     const int bitcount = size(); | |
| 
 | |
|     int nibble_ndx = 0; | |
| 
 | |
|     while( rstart > rend ) | |
|     { | |
|         int cc = *rstart--; | |
| 
 | |
|         if( cc == '_' ) | |
|             continue; | |
| 
 | |
|         int nibble; | |
| 
 | |
|         if( cc >= '0' && cc <= '9' ) | |
|             nibble = cc - '0'; | |
|         else if( cc >= 'a' && cc <= 'f' ) | |
|             nibble = cc - 'a' + 10; | |
|         else if( cc >= 'A' && cc <= 'F' ) | |
|             nibble = cc - 'A' + 10; | |
|         else | |
|             break; | |
| 
 | |
|         int bit = nibble_ndx * 4; | |
| 
 | |
|         for( int ndx=0; bit<bitcount && ndx<4; ++bit, ++ndx ) | |
|             if( nibble & (1<<ndx) ) | |
|                 tmp.set( bit ); | |
| 
 | |
|         if( bit >= bitcount ) | |
|             break; | |
| 
 | |
|         ++nibble_ndx; | |
|     } | |
| 
 | |
|     int byte_count = aStart + aCount - 1 - rstart; | |
| 
 | |
|     assert( byte_count >= 0 ); | |
| 
 | |
|     if( byte_count > 0 ) | |
|         *this = tmp; | |
| 
 | |
|     return byte_count; | |
| } | |
| 
 | |
| 
 | |
| LSEQ LSET::Seq( const PCB_LAYER_ID* aWishListSequence, unsigned aCount ) const | |
| { | |
|     LSEQ ret; | |
| 
 | |
| #if defined(DEBUG) && 0 | |
|     LSET    dup_detector; | |
| 
 | |
|     for( unsigned i=0; i<aCount;  ++i ) | |
|     { | |
|         PCB_LAYER_ID id = aWishListSequence[i]; | |
| 
 | |
|         if( test( id ) ) | |
|         { | |
|             wxASSERT_MSG( !dup_detector[id], wxT( "Duplicate in aWishListSequence" ) ); | |
|             dup_detector[id] = true; | |
| 
 | |
|             ret.push_back( id ); | |
|         } | |
|     } | |
| #else | |
|  | |
|     for( unsigned i=0; i<aCount;  ++i ) | |
|     { | |
|         PCB_LAYER_ID id = aWishListSequence[i]; | |
| 
 | |
|         if( test( id ) ) | |
|             ret.push_back( id ); | |
|     } | |
| #endif | |
|  | |
|     return ret; | |
| } | |
| 
 | |
| 
 | |
| LSEQ LSET::Seq() const | |
| { | |
|     LSEQ    ret; | |
| 
 | |
|     for( unsigned i=0;  i<size();  ++i ) | |
|     { | |
|         if( test(i) ) | |
|             ret.push_back( PCB_LAYER_ID( i ) ); | |
|     } | |
| 
 | |
|     return ret; | |
| } | |
| 
 | |
| 
 | |
| LSEQ LSET::SeqStackupBottom2Top() const | |
| { | |
|     // bottom-to-top stack-up layers | |
|     static const PCB_LAYER_ID sequence[] = { | |
|         B_Fab, | |
|         B_CrtYd, | |
|         B_Adhes, | |
|         B_SilkS, | |
|         B_Paste, | |
|         B_Mask, | |
|         B_Cu, | |
|         In30_Cu, | |
|         In29_Cu, | |
|         In28_Cu, | |
|         In27_Cu, | |
|         In26_Cu, | |
|         In25_Cu, | |
|         In24_Cu, | |
|         In23_Cu, | |
|         In22_Cu, | |
|         In21_Cu, | |
|         In20_Cu, | |
|         In19_Cu, | |
|         In18_Cu, | |
|         In17_Cu, | |
|         In16_Cu, | |
|         In15_Cu, | |
|         In14_Cu, | |
|         In13_Cu, | |
|         In12_Cu, | |
|         In11_Cu, | |
|         In10_Cu, | |
|         In9_Cu, | |
|         In8_Cu, | |
|         In7_Cu, | |
|         In6_Cu, | |
|         In5_Cu, | |
|         In4_Cu, | |
|         In3_Cu, | |
|         In2_Cu, | |
|         In1_Cu, | |
|         F_Cu, | |
|         F_Mask, | |
|         F_Paste, | |
|         F_SilkS, | |
|         F_Adhes, | |
|         F_CrtYd, | |
|         F_Fab, | |
|         Dwgs_User, | |
|         Cmts_User, | |
|         Eco1_User, | |
|         Eco2_User, | |
|         Margin, | |
|         Edge_Cuts, | |
|     }; | |
| 
 | |
|     return Seq( sequence, arrayDim( sequence ) ); | |
| } | |
| 
 | |
| 
 | |
| PCB_LAYER_ID FlipLayer( PCB_LAYER_ID aLayerId, int aCopperLayersCount ) | |
| { | |
|     switch( aLayerId ) | |
|     { | |
|     case B_Cu:              return F_Cu; | |
|     case F_Cu:              return B_Cu; | |
| 
 | |
|     case B_SilkS:           return F_SilkS; | |
|     case F_SilkS:           return B_SilkS; | |
| 
 | |
|     case B_Adhes:           return F_Adhes; | |
|     case F_Adhes:           return B_Adhes; | |
| 
 | |
|     case B_Mask:            return F_Mask; | |
|     case F_Mask:            return B_Mask; | |
| 
 | |
|     case B_Paste:           return F_Paste; | |
|     case F_Paste:           return B_Paste; | |
| 
 | |
|     case B_CrtYd:           return F_CrtYd; | |
|     case F_CrtYd:           return B_CrtYd; | |
| 
 | |
|     case B_Fab:             return F_Fab; | |
|     case F_Fab:             return B_Fab; | |
| 
 | |
|     default:    // change internal layer if aCopperLayersCount is >= 4 | |
|         if( IsCopperLayer( aLayerId ) && aCopperLayersCount >= 4 ) | |
|         { | |
|             // internal copper layers count is aCopperLayersCount-2 | |
|             PCB_LAYER_ID fliplayer = PCB_LAYER_ID(aCopperLayersCount - 2 - ( aLayerId - In1_Cu ) ); | |
|             // Ensure fliplayer has a value which does not crash pcbnew: | |
|             if( fliplayer < F_Cu ) | |
|                 fliplayer = F_Cu; | |
| 
 | |
|             if( fliplayer > B_Cu ) | |
|                 fliplayer = B_Cu; | |
| 
 | |
|             return fliplayer; | |
|         } | |
| 
 | |
|         // No change for the other layers | |
|         return aLayerId; | |
|     } | |
| } | |
| 
 | |
| 
 | |
| LSET FlipLayerMask( LSET aMask, int aCopperLayersCount ) | |
| { | |
|     // layers on physical outside of a board: | |
|     const static LSET and_mask( 16,     // !! update count | |
|                 B_Cu,       F_Cu, | |
|                 B_SilkS,    F_SilkS, | |
|                 B_Adhes,    F_Adhes, | |
|                 B_Mask,     F_Mask, | |
|                 B_Paste,    F_Paste, | |
|                 B_Adhes,    F_Adhes, | |
|                 B_CrtYd,    F_CrtYd, | |
|                 B_Fab,      F_Fab | |
|                 ); | |
| 
 | |
|     LSET newMask = aMask & ~and_mask; | |
| 
 | |
|     if( aMask[B_Cu] ) | |
|         newMask.set( F_Cu ); | |
| 
 | |
|     if( aMask[F_Cu] ) | |
|         newMask.set( B_Cu ); | |
| 
 | |
|     if( aMask[B_SilkS] ) | |
|         newMask.set( F_SilkS ); | |
| 
 | |
|     if( aMask[F_SilkS] ) | |
|         newMask.set( B_SilkS ); | |
| 
 | |
|     if( aMask[B_Adhes] ) | |
|         newMask.set( F_Adhes ); | |
| 
 | |
|     if( aMask[F_Adhes] ) | |
|         newMask.set( B_Adhes ); | |
| 
 | |
|     if( aMask[B_Mask] ) | |
|         newMask.set( F_Mask ); | |
| 
 | |
|     if( aMask[F_Mask] ) | |
|         newMask.set( B_Mask ); | |
| 
 | |
|     if( aMask[B_Paste] ) | |
|         newMask.set( F_Paste ); | |
| 
 | |
|     if( aMask[F_Paste] ) | |
|         newMask.set( B_Paste ); | |
| 
 | |
|     if( aMask[B_Adhes] ) | |
|         newMask.set( F_Adhes ); | |
| 
 | |
|     if( aMask[F_Adhes] ) | |
|         newMask.set( B_Adhes ); | |
| 
 | |
|     if( aMask[B_CrtYd] ) | |
|         newMask.set( F_CrtYd ); | |
| 
 | |
|     if( aMask[F_CrtYd] ) | |
|         newMask.set( B_CrtYd ); | |
| 
 | |
|     if( aMask[B_Fab] ) | |
|         newMask.set( F_Fab ); | |
| 
 | |
|     if( aMask[F_Fab] ) | |
|         newMask.set( B_Fab ); | |
| 
 | |
|     if( aCopperLayersCount >= 4 )   // Internal layers exist | |
|     { | |
|         LSET internalMask = aMask & LSET::InternalCuMask(); | |
| 
 | |
|         if( internalMask != LSET::InternalCuMask() ) | |
|         { | |
|             // the mask does not include all internal layers. Therefore | |
|             // the flipped mask for internal copper layers must be built | |
|             int innerLayerCnt = aCopperLayersCount -2; | |
| 
 | |
|             // the flipped mask is the innerLayerCnt bits rewritten in reverse order | |
|             // ( bits innerLayerCnt to 1 rewritten in bits 1 to innerLayerCnt ) | |
|             for( int ii = 0; ii < innerLayerCnt; ii++ ) | |
|             { | |
|                 if( internalMask[innerLayerCnt - ii] ) | |
|                 { | |
|                     newMask.set( ii + In1_Cu ); | |
|                 } | |
|                 else | |
|                 { | |
|                     newMask.reset( ii + In1_Cu ); | |
|                 } | |
|             } | |
|         } | |
|     } | |
| 
 | |
|     return newMask; | |
| } | |
| 
 | |
| 
 | |
| PCB_LAYER_ID LSET::ExtractLayer() const | |
| { | |
|     unsigned set_count = count(); | |
| 
 | |
|     if( !set_count ) | |
|         return UNSELECTED_LAYER; | |
|     else if( set_count > 1 ) | |
|         return UNDEFINED_LAYER; | |
| 
 | |
|     for( unsigned i=0; i < size(); ++i ) | |
|     { | |
|         if( test( i ) ) | |
|             return PCB_LAYER_ID( i ); | |
|     } | |
| 
 | |
|     wxASSERT( 0 );  // set_count was verified as 1 above, what did you break? | |
|  | |
|     return UNDEFINED_LAYER; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::InternalCuMask() | |
| { | |
|     static const PCB_LAYER_ID cu_internals[] = { | |
|         In1_Cu, | |
|         In2_Cu, | |
|         In3_Cu, | |
|         In4_Cu, | |
|         In5_Cu, | |
|         In6_Cu, | |
|         In7_Cu, | |
|         In8_Cu, | |
|         In9_Cu, | |
|         In10_Cu, | |
|         In11_Cu, | |
|         In12_Cu, | |
|         In13_Cu, | |
|         In14_Cu, | |
|         In15_Cu, | |
|         In16_Cu, | |
|         In17_Cu, | |
|         In18_Cu, | |
|         In19_Cu, | |
|         In20_Cu, | |
|         In21_Cu, | |
|         In22_Cu, | |
|         In23_Cu, | |
|         In24_Cu, | |
|         In25_Cu, | |
|         In26_Cu, | |
|         In27_Cu, | |
|         In28_Cu, | |
|         In29_Cu, | |
|         In30_Cu, | |
|     }; | |
| 
 | |
|     static const LSET saved( cu_internals, arrayDim( cu_internals ) ); | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::AllCuMask( int aCuLayerCount ) | |
| { | |
|     // retain all in static as the full set, which is a common case. | |
|     static const LSET  all = InternalCuMask().set( F_Cu ).set( B_Cu ); | |
| 
 | |
|     if( aCuLayerCount == MAX_CU_LAYERS ) | |
|         return all; | |
| 
 | |
|     // subtract out some Cu layers not wanted in the mask. | |
|     LSET    ret = all; | |
|     int     clear_count = MAX_CU_LAYERS - aCuLayerCount; | |
| 
 | |
|     clear_count = Clamp( 0, clear_count, MAX_CU_LAYERS - 2 ); | |
| 
 | |
|     for( LAYER_NUM elem=In30_Cu;  clear_count; --elem, --clear_count ) | |
|     { | |
|         ret.set( elem, false ); | |
|     } | |
| 
 | |
|     return ret; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::AllNonCuMask() | |
| { | |
|     static const LSET saved = LSET().set() & ~AllCuMask(); | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::ExternalCuMask() | |
| { | |
|     static const LSET saved( 2, F_Cu, B_Cu ); | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::AllLayersMask() | |
| { | |
|     static const LSET saved = LSET().set(); | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::BackTechMask() | |
| { | |
|     static const LSET saved( 6, B_SilkS, B_Mask, B_Adhes, B_Paste, B_CrtYd, B_Fab ); | |
|     return saved; | |
| } | |
| 
 | |
| LSET LSET::BackBoardTechMask() | |
| { | |
|     static const LSET saved( 4, B_SilkS, B_Mask, B_Adhes, B_Paste ); | |
|     return saved; | |
| } | |
| 
 | |
| LSET LSET::FrontTechMask() | |
| { | |
|     static const LSET saved( 6, F_SilkS, F_Mask, F_Adhes, F_Paste, F_CrtYd, F_Fab ); | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::FrontBoardTechMask() | |
| { | |
|     static const LSET saved( 4, F_SilkS, F_Mask, F_Adhes, F_Paste ); | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::AllTechMask() | |
| { | |
|     static const LSET saved = BackTechMask() | FrontTechMask(); | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::AllBoardTechMask() | |
| { | |
|     static const LSET saved = BackBoardTechMask() | FrontBoardTechMask(); | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::UserMask() | |
| { | |
|     static const LSET saved( 6, | |
|         Dwgs_User, | |
|         Cmts_User, | |
|         Eco1_User, | |
|         Eco2_User, | |
|         Edge_Cuts, | |
|         Margin | |
|         ); | |
| 
 | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::FrontMask() | |
| { | |
|     static const LSET saved = FrontTechMask().set( F_Cu ); | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::BackMask() | |
| { | |
|     static const LSET saved = BackTechMask().set( B_Cu ); | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::ForbiddenFootprintLayers() | |
| { | |
|     static const LSET saved = InternalCuMask().set( Edge_Cuts ).set( Margin ); | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSET LSET::ForbiddenTextLayers() | |
| { | |
|     static const LSET saved( 1, Edge_Cuts ); | |
|     return saved; | |
| } | |
| 
 | |
| 
 | |
| LSEQ LSET::UIOrder() const | |
| { | |
|     LSEQ order = CuStack(); | |
|     LSEQ techuser = TechAndUserUIOrder(); | |
|     order.insert( order.end(), techuser.begin(), techuser.end() ); | |
| 
 | |
|     return order; | |
| } | |
| 
 | |
| 
 | |
| PCB_LAYER_ID ToLAYER_ID( int aLayer ) | |
| { | |
|     wxASSERT( aLayer < GAL_LAYER_ID_END ); | |
|     return PCB_LAYER_ID( aLayer ); | |
| } | |
| 
 |