/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2014 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2010 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2007 KiCad Developers, see change_log.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 */ /** * @file layers_id_colors_and_visibility.h * @brief Board layer functions and definitions. */ #ifndef LAYERS_ID_AND_VISIBILITY_H_ #define LAYERS_ID_AND_VISIBILITY_H_ #include #include #include #include class BOARD; /** * Type LAYER_NUM * can be replaced with int and removed. Until then, it is something you can increment, * and its meaning is only advisory but can extend beyond PCB layers into view layers * and gerber layers. */ typedef int LAYER_NUM; /** * Enum LAYER_ID * is the set of PCB layers. It has nothing to do with gerbers or view layers. * One of these cannot be "incremented". */ enum LAYER_ID #if __cplusplus >= 201103L : unsigned char #endif { F_Cu, // 0 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 B_Adhes, F_Adhes, B_Paste, F_Paste, B_SilkS, F_SilkS, B_Mask, F_Mask, Dwgs_User, Cmts_User, Eco1_User, Eco2_User, Edge_Cuts, Margin, B_CrtYd, F_CrtYd, B_Fab, F_Fab, LAYER_ID_COUNT }; #define UNDEFINED_LAYER LAYER_ID(-1) #define UNSELECTED_LAYER LAYER_ID(-2) #define MAX_CU_LAYERS (B_Cu - F_Cu + 1) /// A sequence of layers, a sequence provides a certain order. typedef std::vector BASE_SEQ; /** * Class LSEQ * is a sequence (and therefore also a set) of LAYER_IDs. A sequence provides * a certain order. *

* It can also be used as an iterator: * * * for( LSEQ cu_stack = aSet.CuStack(); cu_stack; ++cu_stack ) * { * layer_id = *cu_stack; * : * things to do with layer_id; * } * * */ class LSEQ : public BASE_SEQ { unsigned m_index; public: LSEQ() : m_index( 0 ) {} template LSEQ( InputIterator start, InputIterator end ) : BASE_SEQ( start, end ), m_index( 0 ) {} void Rewind() { m_index = 0; } void operator ++ () { ++m_index; } // returns nothing, used in simple statements only. void operator ++ (int) { ++m_index; } operator bool () { return m_index < size(); } LAYER_ID operator * () const { return at( m_index ); // throws std::out_of_range } }; typedef std::bitset BASE_SET; /** * Class LSET * is a set of LAYER_IDs. It can be converted to numerous purpose LSEQs using * the various member functions, most of which are based on Seq(). The advantage * of converting to LSEQ using purposeful code, is it removes any dependency * on order/sequence inherent in this set. */ class LSET : public BASE_SET { public: // The constructor flavors are carefully chosen to prevent LSET( int ) from compiling. // That excludes "LSET s = 0;" and excludes "LSET s = -1;", etc. // LSET s = 0; needs to be removed from the code, this accomplishes that. // Remember LSET( LAYER_ID(0) ) sets bit 0, so "LSET s = 0;" is illegal // to prevent that surprize. Therefore LSET's constructor suite is significantly // different than the base class from which it is derived. // Other member functions (non-constructor functions) are identical to the base // class's and therefore are re-used from the base class. /** * Constructor LSET() * creates an empty (cleared) set. */ LSET() : BASE_SET() // all bits are set to zero in BASE_SET() { } LSET( const BASE_SET& aOther ) : BASE_SET( aOther ) { } /** * Constructor LSET( LAYER_ID ) * takes a LAYER_ID and sets that bit. This makes the following code into * a bug: * * LSET s = 0; * * Instead use: * * * LSET s; * * * for an empty set. */ LSET( LAYER_ID aLayer ) : // LAYER_ID deliberately exludes int and relatives BASE_SET() { set( aLayer ); } /** * Constructor LSET( const LAYER_ID* aArray, unsigned aCount ) * works well with an arry or LSEQ. */ LSET( const LAYER_ID* aArray, unsigned aCount ); /** * Constructor LSET( unsigned, LAYER_ID, ...) * takes one or more LAYER_IDs in the argument list to construct * the set. Typically only used in static construction. * * @param aIdCount is the number of LAYER_IDs which follow. * @param aFirst is the first included in @a aIdCount and must always be present, and can * be followed by any number of additional LAYER_IDs so long as @a aIdCount accurately * reflects the count. */ LSET( unsigned aIdCount, LAYER_ID aFirst, ... ); // args chosen to prevent LSET( int ) from compiling /** * Function Name * returns the fixed name association with aLayerId. */ static const wxChar* Name( LAYER_ID aLayerId ); /** * Function InternalCuMask() * returns a complete set of internal copper layers, which is all Cu layers * except F_Cu and B_Cu. */ static LSET InternalCuMask(); /** * Function AllCuMask * returns a mask holding the requested number of Cu LAYER_IDs. */ static LSET AllCuMask( int aCuLayerCount = MAX_CU_LAYERS ); /** * Function AllNonCuMask * returns a mask holding all layer minus CU layers. */ static LSET AllNonCuMask(); static LSET AllLayersMask(); /** * Function FrontTechMask * returns a mask holding all technical layers (no CU layer) on front side. */ static LSET FrontTechMask(); /** * Function BackTechMask * returns a mask holding all technical layers (no CU layer) on back side. */ static LSET BackTechMask(); static LSET AllTechMask(); /** * Function FrontMask * returns a mask holding all technical layers and the external CU layer on front side. */ static LSET FrontMask(); /** * Function BackMask * returns a mask holding all technical layers and the external CU layer on back side. */ static LSET BackMask(); static LSET UserMask(); /** * Function CuStack * returns a sequence of copper layers in starting from the front/top * and extending to the back/bottom. This specific sequence is depended upon * in numerous places. */ LSEQ CuStack() const; /** * Function Technicals * returns a sequence of technical layers. A sequence provides a certain * order. * @param aSubToOmit is the subset of the techical layers to omit, defaults to none. */ LSEQ Technicals( LSET aSubToOmit = LSET() ) const; /// *_User layers. LSEQ Users() const; LSEQ UIOrder() const; /** * Function Seq * returns an LSEQ from the union of this LSET and a desired sequence. The LSEQ * element will be in the same sequence as aWishListSequence if they are present. * @param aWishListSequence establishes the order of the returned LSEQ, and the LSEQ will only * contiain LAYER_IDs which are present in this set. * @param aCount is the length of aWishListSequence array. */ LSEQ Seq( const LAYER_ID* aWishListSequence, unsigned aCount ) const; /** * Function Seq * returns a LSEQ from this LSET in ascending LAYER_ID order. Each LSEQ * element will be in the same sequence as in LAYER_ID and only present * in the resultant LSEQ if present in this set. Therefore the sequence is * subject to change, use it only when enumeration and not order is important. */ LSEQ Seq() const; /** * Function SeqStackBottom2Top * returns the sequence that is typical for a bottom-to-top stack-up. * For instance, to plot multiple layers in a single image, the top layers output last. */ LSEQ SeqStackupBottom2Top() const; /** * Function FmtHex * returns a hex string showing contents of this LSEQ. */ std::string FmtHex() const; /** * Function ParseHex * understands the output of FmtHex() and replaces this set's values * with those given in the input string. Parsing stops at the first * non hex ASCII byte, except that marker bytes output from FmtHex are * not terminators. * @return int - number of bytes consumed */ int ParseHex( const char* aStart, int aCount ); /** * Function FmtBin * returns a binary string showing contents of this LSEQ. */ std::string FmtBin() const; /** * Find the first set LAYER_ID. Returns UNDEFINED_LAYER if more * than one is set or UNSELECTED_LAYER if none is set. */ LAYER_ID ExtractLayer() const; private: /// Take this off the market, it may not be used because of LSET( LAYER_ID ). LSET( unsigned long __val ) { // not usable, it's private. } }; /** * Enum PCB_VISIBLE * is a set of visible PCB elements. * @see BOARD::SetVisibleElementColor() * @see BOARD::SetVisibleElement() */ enum PCB_VISIBLE { VIAS_VISIBLE, VIA_MICROVIA_VISIBLE, VIA_BBLIND_VISIBLE, VIA_THROUGH_VISIBLE, NON_PLATED_VISIBLE, MOD_TEXT_FR_VISIBLE, MOD_TEXT_BK_VISIBLE, MOD_TEXT_INVISIBLE, ///< text marked as invisible ANCHOR_VISIBLE, PAD_FR_VISIBLE, PAD_BK_VISIBLE, RATSNEST_VISIBLE, GRID_VISIBLE, // the rest of these do not currently support color changes: NO_CONNECTS_VISIBLE, ///< show a marker on pads with no nets MOD_FR_VISIBLE, ///< show modules on front MOD_BK_VISIBLE, ///< show modules on back MOD_VALUES_VISIBLE, ///< show modules values (when texts are visibles) MOD_REFERENCES_VISIBLE, ///< show modules references (when texts are visibles) TRACKS_VISIBLE, PADS_VISIBLE, ///< multilayer pads, usually with holes PADS_HOLES_VISIBLE, VIAS_HOLES_VISIBLE, DRC_VISIBLE, ///< drc markers WORKSHEET, ///< worksheet frame GP_OVERLAY, ///< general purpose overlay END_PCB_VISIBLE_LIST // sentinel }; // Some elements do not have yet a visibility control // from a dialog, but have a visibility control flag. // Here is a mask to set them visible, to be sure they are displayed // after loading a board for instance #define MIN_VISIBILITY_MASK int( (1 << TRACKS_VISIBLE) +\ (1 << PADS_VISIBLE) +\ (1 << PADS_HOLES_VISIBLE) +\ (1 << VIAS_HOLES_VISIBLE) +\ (1 << DRC_VISIBLE) +\ (1 << WORKSHEET) +\ (1 << GP_OVERLAY) ) /** * Enum NETNAMES_VISIBLE * is a set of layers specific for displaying net names. * Their visiblity is not supposed to be saved in a board file, * they are only to be used by the GAL. */ #if 0 // was: enum NETNAMES_VISIBLE { LAYER_1_NETNAMES_VISIBLE, // bottom layer LAYER_2_NETNAMES_VISIBLE, LAYER_3_NETNAMES_VISIBLE, LAYER_4_NETNAMES_VISIBLE, LAYER_5_NETNAMES_VISIBLE, LAYER_6_NETNAMES_VISIBLE, LAYER_7_NETNAMES_VISIBLE, LAYER_8_NETNAMES_VISIBLE, LAYER_9_NETNAMES_VISIBLE, LAYER_10_NETNAMES_VISIBLE, LAYER_11_NETNAMES_VISIBLE, LAYER_12_NETNAMES_VISIBLE, LAYER_13_NETNAMES_VISIBLE, LAYER_14_NETNAMES_VISIBLE, LAYER_15_NETNAMES_VISIBLE, LAYER_16_NETNAMES_VISIBLE, // top layer PAD_FR_NETNAMES_VISIBLE, PAD_BK_NETNAMES_VISIBLE, PADS_NETNAMES_VISIBLE, END_NETNAMES_VISIBLE_LIST // sentinel }; #else enum NETNAMES_VISIBLE { PAD_FR_NETNAMES_VISIBLE = B_Cu+1, PAD_BK_NETNAMES_VISIBLE, PADS_NETNAMES_VISIBLE, END_NETNAMES_VISIBLE_LIST // sentinel }; #endif /// macro for obtaining layer number for specific item (eg. pad or text) #define ITEM_GAL_LAYER(layer) (LAYER_ID_COUNT + layer) #define NETNAMES_GAL_LAYER(layer) (LAYER_ID_COUNT + END_PCB_VISIBLE_LIST + layer ) /// number of *all* GAL layers including PCB and item layers #define TOTAL_LAYER_COUNT (LAYER_ID_COUNT + END_PCB_VISIBLE_LIST + END_NETNAMES_VISIBLE_LIST) /** * Function IsValidLayer * tests whether a given integer is a valid layer index, i.e. can * be safely put in a LAYER_ID * @param aLayerId = Layer index to test. It can be an int, so its * useful during I/O * @return true if aLayerIndex is a valid layer index */ inline bool IsValidLayer( LAYER_NUM aLayerId ) { return unsigned( aLayerId ) < LAYER_ID_COUNT; } /** * Function IsPcbLayer * tests whether a layer is a valid layer for pcbnew * @param aLayer = Layer to test * @return true if aLayer is a layer valid in pcbnew */ inline bool IsPcbLayer( LAYER_NUM aLayer ) { return aLayer >= F_Cu && aLayer < LAYER_ID_COUNT; } /** * Function IsCopperLayer * tests whether a layer is a copper layer * @param aLayerId = Layer to test * @return true if aLayer is a valid copper layer */ inline bool IsCopperLayer( LAYER_NUM aLayerId ) { return aLayerId >= F_Cu && aLayerId <= B_Cu; } /** * Function IsNonCopperLayer * tests whether a layer is a non copper layer * @param aLayerId = Layer to test * @return true if aLayer is a non copper layer */ inline bool IsNonCopperLayer( LAYER_NUM aLayerId ) { return aLayerId > B_Cu && aLayerId <= LAYER_ID_COUNT; } /** * Function IsUserLayer * tests whether a layer is a non copper and a non tech layer * @param aLayerId = Layer to test * @return true if aLayer is a user layer */ inline bool IsUserLayer( LAYER_ID aLayerId ) { return aLayerId >= Dwgs_User && aLayerId <= Eco2_User; } /* IMPORTANT: If a layer is not a front layer not necessarily is true the converse. The same hold for a back layer. So a layer can be: - Front - Back - Neither (internal or auxiliary) The check most frequent is for back layers, since it involves flips */ /** * Layer classification: check if it's a front layer */ inline bool IsFrontLayer( LAYER_ID aLayerId ) { switch( aLayerId ) { case F_Cu: case F_Adhes: case F_Paste: case F_SilkS: case F_Mask: case F_CrtYd: case F_Fab: return true; default: ; } return false; } /** * Layer classification: check if it's a back layer */ inline bool IsBackLayer( LAYER_ID aLayerId ) { switch( aLayerId ) { case B_Cu: case B_Adhes: case B_Paste: case B_SilkS: case B_Mask: case B_CrtYd: case B_Fab: return true; default: ; } return false; } /** * Function FlippedLayerNumber * @return the layer number after flipping an item * some (not all) layers: external copper, and paired layers( Mask, Paste, solder ... ) * are swapped between front and back sides * internal layers are flipped only if the copper layers count is known * @param aLayer = the LAYER_ID to flip * @param aCopperLayersCount = the number of copper layers. if 0 (in fact if < 4 ) * internal layers will be not flipped because the layer count is not known */ LAYER_ID FlipLayer( LAYER_ID aLayerId, int aCopperLayersCount = 0 ); /** * Calculate the mask layer when flipping a footprint * BACK and FRONT copper layers, mask, paste, solder layers are swapped * internal layers are flipped only if the copper layers count is known * @param aMask = the LSET to flip * @param aCopperLayersCount = the number of copper layers. if 0 (in fact if < 4 ) * internal layers will be not flipped because the layer count is not known */ LSET FlipLayerMask( LSET aMask, int aCopperLayersCount = 0 ); /** * Return a string (to be shown to the user) describing a layer mask. * Useful for showing where is a pad, track, entity, etc. * The BOARD is needed because layer names are (somewhat) customizable */ wxString LayerMaskDescribe( const BOARD* aBoard, LSET aMask ); /** * Returns a netname layer corresponding to the given layer. */ inline int GetNetnameLayer( int aLayer ) { if( IsCopperLayer( aLayer ) ) return NETNAMES_GAL_LAYER( aLayer ); else if( aLayer == ITEM_GAL_LAYER( PADS_VISIBLE ) ) return NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE ); else if( aLayer == ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ) return NETNAMES_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE ); else if( aLayer == ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ) return NETNAMES_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE ); // Fallback return Cmts_User; } /** * Function IsNetnameLayer * tests whether a layer is a netname layer * @param aLayer = Layer to test * @return true if aLayer is a valid netname layer */ inline bool IsNetnameLayer( LAYER_NUM aLayer ) { return aLayer >= NETNAMES_GAL_LAYER( F_Cu ) && aLayer < NETNAMES_GAL_LAYER( END_NETNAMES_VISIBLE_LIST ); } LAYER_ID ToLAYER_ID( int aLayer ); #endif // LAYERS_ID_AND_VISIBILITY_H_