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.

332 lines
9.8 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software: you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation, either version 3 of the License, or (at your
  9. * option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef LSET_H
  20. #define LSET_H
  21. #include <bitset>
  22. #include <layer_ids.h>
  23. class LSEQ;
  24. typedef std::bitset<PCB_LAYER_ID_COUNT> BASE_SET;
  25. /**
  26. * LSET is a set of PCB_LAYER_IDs. It can be converted to numerous purpose LSEQs using
  27. * the various member functions, most of which are based on Seq(). The advantage
  28. * of converting to LSEQ using purposeful code, is it removes any dependency
  29. * on order/sequence inherent in this set.
  30. */
  31. class KICOMMON_API LSET : public BASE_SET
  32. {
  33. public:
  34. // The constructor flavors are carefully chosen to prevent LSET( int ) from compiling.
  35. // That excludes "LSET s = 0;" and excludes "LSET s = -1;", etc.
  36. // LSET s = 0; needs to be removed from the code, this accomplishes that.
  37. // Remember LSET( PCB_LAYER_ID(0) ) sets bit 0, so "LSET s = 0;" is illegal
  38. // to prevent that surprise. Therefore LSET's constructor suite is significantly
  39. // different than the base class from which it is derived.
  40. // Other member functions (non-constructor functions) are identical to the base
  41. // class's and therefore are re-used from the base class.
  42. /**
  43. * Create an empty (cleared) set.
  44. */
  45. LSET() :
  46. BASE_SET() // all bits are set to zero in BASE_SET()
  47. {
  48. }
  49. LSET( const BASE_SET& aOther ) :
  50. BASE_SET( aOther )
  51. {
  52. }
  53. /**
  54. * Take a PCB_LAYER_ID and sets that bit. This makes the following code into
  55. * a bug:
  56. *
  57. * <code> LSET s = 0; </code>
  58. *
  59. * Instead use:
  60. *
  61. * <code>
  62. * LSET s;
  63. * </code>
  64. *
  65. * for an empty set.
  66. */
  67. LSET( PCB_LAYER_ID aLayer ) : // PCB_LAYER_ID deliberately excludes int and relatives
  68. BASE_SET()
  69. {
  70. set( aLayer );
  71. }
  72. /**
  73. * Create an array or LSEQ.
  74. */
  75. LSET( const PCB_LAYER_ID* aArray, unsigned aCount );
  76. /**
  77. * Take one or more PCB_LAYER_IDs in the argument list to construct the set. Typically
  78. * only used in static construction.
  79. *
  80. * @param aIdCount is the number of PCB_LAYER_IDs which follow.
  81. * @param aFirst is the first included in @a aIdCount and must always be present, and can
  82. * be followed by any number of additional PCB_LAYER_IDs so long as @a aIdCount accurately
  83. * reflects the count.
  84. *
  85. * Parameter is 'int' to avoid va_start undefined behavior.
  86. */
  87. LSET( unsigned aIdCount, int aFirst, ... ); // args chosen to prevent LSET( int ) from compiling
  88. LSET( const LSEQ& aSeq );
  89. LSET( unsigned long __val ) = delete;
  90. /**
  91. * See if the layer set contains a PCB layer.
  92. *
  93. * @param aLayer is the layer to check
  94. * @return true if the layer is included
  95. */
  96. bool Contains( PCB_LAYER_ID aLayer )
  97. {
  98. try
  99. {
  100. return test( aLayer );
  101. }
  102. catch( std::out_of_range& )
  103. {
  104. return false;
  105. }
  106. }
  107. /**
  108. * Return the fixed name association with aLayerId.
  109. */
  110. static const wxChar* Name( PCB_LAYER_ID aLayerId );
  111. /**
  112. * Return a complete set of internal copper layers which is all Cu layers
  113. * except F_Cu and B_Cu.
  114. */
  115. static LSET InternalCuMask();
  116. /**
  117. * Return a complete set of all top assembly layers which is all F_SilkS and F_Mask
  118. */
  119. static LSET FrontAssembly();
  120. /**
  121. * Return a complete set of all bottom assembly layers which is all B_SilkS and B_Mask
  122. */
  123. static LSET BackAssembly();
  124. /**
  125. * Return a mask holding the requested number of Cu PCB_LAYER_IDs.
  126. */
  127. static LSET AllCuMask( int aCuLayerCount = MAX_CU_LAYERS );
  128. /**
  129. * Return a mask holding the Front and Bottom layers.
  130. */
  131. static LSET ExternalCuMask();
  132. /**
  133. * Return a mask holding all layer minus CU layers.
  134. */
  135. static LSET AllNonCuMask();
  136. static LSET AllLayersMask();
  137. /**
  138. * Return a mask holding all technical layers (no CU layer) on front side.
  139. */
  140. static LSET FrontTechMask();
  141. /**
  142. * Return a mask holding technical layers used in a board fabrication
  143. * (no CU layer) on front side.
  144. */
  145. static LSET FrontBoardTechMask();
  146. /**
  147. * Return a mask holding all technical layers (no CU layer) on back side.
  148. */
  149. static LSET BackTechMask();
  150. /**
  151. * Return a mask holding technical layers used in a board fabrication
  152. * (no CU layer) on Back side.
  153. */
  154. static LSET BackBoardTechMask();
  155. /**
  156. * Return a mask holding all technical layers (no CU layer) on both side.
  157. */
  158. static LSET AllTechMask();
  159. /**
  160. * Return a mask holding board technical layers (no CU layer) on both side.
  161. */
  162. static LSET AllBoardTechMask();
  163. /**
  164. * Return a mask holding all technical layers and the external CU layer on front side.
  165. */
  166. static LSET FrontMask();
  167. /**
  168. * Return a mask holding all technical layers and the external CU layer on back side.
  169. */
  170. static LSET BackMask();
  171. static LSET SideSpecificMask();
  172. static LSET UserMask();
  173. /**
  174. * Return a mask holding all layers which are physically realized. Equivalent to the copper
  175. * layers + the board tech mask.
  176. */
  177. static LSET PhysicalLayersMask();
  178. /**
  179. * Return a mask with all of the allowable user defined layers.
  180. */
  181. static LSET UserDefinedLayers();
  182. /**
  183. * Layers which are not allowed within footprint definitions. Currently internal
  184. * copper layers and Margin.
  185. */
  186. static LSET ForbiddenFootprintLayers();
  187. /**
  188. * Return a sequence of copper layers in starting from the front/top
  189. * and extending to the back/bottom. This specific sequence is depended upon
  190. * in numerous places.
  191. */
  192. LSEQ CuStack() const;
  193. /**
  194. * Return a sequence of technical layers. A sequence provides a certain order.
  195. *
  196. * @param aSubToOmit is the subset of the technical layers to omit, defaults to none.
  197. */
  198. LSEQ Technicals( LSET aSubToOmit = LSET() ) const;
  199. /// *_User layers.
  200. LSEQ Users() const;
  201. /// Returns the technical and user layers in the order shown in layer widget
  202. LSEQ TechAndUserUIOrder() const;
  203. LSEQ UIOrder() const;
  204. /**
  205. * Return an LSEQ from the union of this LSET and a desired sequence. The LSEQ
  206. * element will be in the same sequence as aWishListSequence if they are present.
  207. * @param aWishListSequence establishes the order of the returned LSEQ, and the LSEQ will only
  208. * contain PCB_LAYER_IDs which are present in this set.
  209. * @param aCount is the length of aWishListSequence array.
  210. */
  211. LSEQ Seq( const PCB_LAYER_ID* aWishListSequence, unsigned aCount ) const;
  212. LSEQ Seq( const LSEQ& aSequence ) const;
  213. /**
  214. * Return a LSEQ from this LSET in ascending PCB_LAYER_ID order. Each LSEQ
  215. * element will be in the same sequence as in PCB_LAYER_ID and only present
  216. * in the resultant LSEQ if present in this set. Therefore the sequence is
  217. * subject to change, use it only when enumeration and not order is important.
  218. */
  219. LSEQ Seq() const;
  220. /**
  221. * Generate a sequence of layers that represent a top to bottom stack of this set of layers.
  222. *
  223. * @param aSelectedLayer is the layer to put at the top of stack when defined.
  224. *
  225. * @return the top to bottom layer sequence.
  226. */
  227. LSEQ SeqStackupTop2Bottom( PCB_LAYER_ID aSelectedLayer = UNDEFINED_LAYER ) const;
  228. /**
  229. * Return the sequence that is typical for a bottom-to-top stack-up.
  230. * For instance, to plot multiple layers in a single image, the top layers output last.
  231. */
  232. LSEQ SeqStackupForPlotting() const;
  233. /**
  234. * Execute a function on each layer of the LSET.
  235. */
  236. void RunOnLayers( const std::function<void( PCB_LAYER_ID )>& aFunction ) const
  237. {
  238. for( size_t ii = 0; ii < size(); ++ii )
  239. {
  240. if( test( ii ) )
  241. aFunction( PCB_LAYER_ID( ii ) );
  242. }
  243. }
  244. /**
  245. * Return a hex string showing contents of this LSEQ.
  246. */
  247. std::string FmtHex() const;
  248. /**
  249. * Convert the output of FmtHex() and replaces this set's values
  250. * with those given in the input string. Parsing stops at the first
  251. * non hex ASCII byte, except that marker bytes output from FmtHex are
  252. * not terminators.
  253. * @return int - number of bytes consumed
  254. */
  255. int ParseHex( const char* aStart, int aCount );
  256. /**
  257. * Return a binary string showing contents of this LSEQ.
  258. */
  259. std::string FmtBin() const;
  260. /**
  261. * Find the first set PCB_LAYER_ID. Returns UNDEFINED_LAYER if more
  262. * than one is set or UNSELECTED_LAYER if none is set.
  263. */
  264. PCB_LAYER_ID ExtractLayer() const;
  265. /**
  266. * Flip the layers in this set.
  267. *
  268. * BACK and FRONT copper layers, mask, paste, solder layers are swapped
  269. * internal layers are flipped only if the copper layers count is known
  270. * @param aMask = the LSET to flip
  271. * @param aCopperLayersCount = the number of copper layers. if 0 (in fact if < 4 )
  272. * internal layers will be not flipped because the layer count is not known
  273. */
  274. LSET& Flip( int aCopperLayersCount = 0 );
  275. };
  276. #endif // LSET_H