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.

948 lines
22 KiB

12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
4 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
  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 <dick@softplc.com>
  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. #include <algorithm>
  25. #include <bitset> // for bitset, __bitset<>::ref...
  26. #include <cassert>
  27. #include <cstdarg>
  28. #include <iostream> // for string, endl, basic_ost...
  29. #include <cstddef> // for size_t
  30. #include <core/arraydim.h>
  31. #include <layer_ids.h> // for PCB_LAYER_ID
  32. #include <lseq.h>
  33. #include <macros.h> // for arrayDim
  34. #include <wx/debug.h> // for wxASSERT, wxASSERT_MSG
  35. #include <wx/string.h>
  36. #include <lset.h>
  37. LSET::LSET( std::initializer_list<PCB_LAYER_ID> aList ) :
  38. LSET()
  39. {
  40. for( PCB_LAYER_ID layer : aList )
  41. set( layer );
  42. }
  43. LSET::LSET( const LSEQ& aSeq ) :
  44. LSET()
  45. {
  46. for( PCB_LAYER_ID layer : aSeq )
  47. set( layer );
  48. }
  49. /**
  50. * NOTE: These names must not be translated or changed. They are used as tokens in the board
  51. * file format because the ordinal value of the PCB_LAYER_ID enum was not stable over time.
  52. * @see LayerName() for what should be used to display the default name of a layer in the GUI.
  53. */
  54. const wxChar* LSET::Name( PCB_LAYER_ID aLayerId )
  55. {
  56. const wxChar* txt;
  57. // using a switch to explicitly show the mapping more clearly
  58. switch( aLayerId )
  59. {
  60. case F_Cu: txt = wxT( "F.Cu" ); break;
  61. case In1_Cu: txt = wxT( "In1.Cu" ); break;
  62. case In2_Cu: txt = wxT( "In2.Cu" ); break;
  63. case In3_Cu: txt = wxT( "In3.Cu" ); break;
  64. case In4_Cu: txt = wxT( "In4.Cu" ); break;
  65. case In5_Cu: txt = wxT( "In5.Cu" ); break;
  66. case In6_Cu: txt = wxT( "In6.Cu" ); break;
  67. case In7_Cu: txt = wxT( "In7.Cu" ); break;
  68. case In8_Cu: txt = wxT( "In8.Cu" ); break;
  69. case In9_Cu: txt = wxT( "In9.Cu" ); break;
  70. case In10_Cu: txt = wxT( "In10.Cu" ); break;
  71. case In11_Cu: txt = wxT( "In11.Cu" ); break;
  72. case In12_Cu: txt = wxT( "In12.Cu" ); break;
  73. case In13_Cu: txt = wxT( "In13.Cu" ); break;
  74. case In14_Cu: txt = wxT( "In14.Cu" ); break;
  75. case In15_Cu: txt = wxT( "In15.Cu" ); break;
  76. case In16_Cu: txt = wxT( "In16.Cu" ); break;
  77. case In17_Cu: txt = wxT( "In17.Cu" ); break;
  78. case In18_Cu: txt = wxT( "In18.Cu" ); break;
  79. case In19_Cu: txt = wxT( "In19.Cu" ); break;
  80. case In20_Cu: txt = wxT( "In20.Cu" ); break;
  81. case In21_Cu: txt = wxT( "In21.Cu" ); break;
  82. case In22_Cu: txt = wxT( "In22.Cu" ); break;
  83. case In23_Cu: txt = wxT( "In23.Cu" ); break;
  84. case In24_Cu: txt = wxT( "In24.Cu" ); break;
  85. case In25_Cu: txt = wxT( "In25.Cu" ); break;
  86. case In26_Cu: txt = wxT( "In26.Cu" ); break;
  87. case In27_Cu: txt = wxT( "In27.Cu" ); break;
  88. case In28_Cu: txt = wxT( "In28.Cu" ); break;
  89. case In29_Cu: txt = wxT( "In29.Cu" ); break;
  90. case In30_Cu: txt = wxT( "In30.Cu" ); break;
  91. case B_Cu: txt = wxT( "B.Cu" ); break;
  92. // Technicals
  93. case B_Adhes: txt = wxT( "B.Adhes" ); break;
  94. case F_Adhes: txt = wxT( "F.Adhes" ); break;
  95. case B_Paste: txt = wxT( "B.Paste" ); break;
  96. case F_Paste: txt = wxT( "F.Paste" ); break;
  97. case B_SilkS: txt = wxT( "B.SilkS" ); break;
  98. case F_SilkS: txt = wxT( "F.SilkS" ); break;
  99. case B_Mask: txt = wxT( "B.Mask" ); break;
  100. case F_Mask: txt = wxT( "F.Mask" ); break;
  101. // Users
  102. case Dwgs_User: txt = wxT( "Dwgs.User" ); break;
  103. case Cmts_User: txt = wxT( "Cmts.User" ); break;
  104. case Eco1_User: txt = wxT( "Eco1.User" ); break;
  105. case Eco2_User: txt = wxT( "Eco2.User" ); break;
  106. case Edge_Cuts: txt = wxT( "Edge.Cuts" ); break;
  107. case Margin: txt = wxT( "Margin" ); break;
  108. // Footprint
  109. case F_CrtYd: txt = wxT( "F.CrtYd" ); break;
  110. case B_CrtYd: txt = wxT( "B.CrtYd" ); break;
  111. case F_Fab: txt = wxT( "F.Fab" ); break;
  112. case B_Fab: txt = wxT( "B.Fab" ); break;
  113. // User definable layers.
  114. case User_1: txt = wxT( "User.1" ); break;
  115. case User_2: txt = wxT( "User.2" ); break;
  116. case User_3: txt = wxT( "User.3" ); break;
  117. case User_4: txt = wxT( "User.4" ); break;
  118. case User_5: txt = wxT( "User.5" ); break;
  119. case User_6: txt = wxT( "User.6" ); break;
  120. case User_7: txt = wxT( "User.7" ); break;
  121. case User_8: txt = wxT( "User.8" ); break;
  122. case User_9: txt = wxT( "User.9" ); break;
  123. // Rescue
  124. case Rescue: txt = wxT( "Rescue" ); break;
  125. default:
  126. std::cout << aLayerId << std::endl;
  127. wxASSERT_MSG( 0, wxT( "aLayerId out of range" ) );
  128. txt = wxT( "BAD INDEX!" ); break;
  129. }
  130. return txt;
  131. }
  132. LSEQ LSET::CuStack() const
  133. {
  134. // desired sequence
  135. static const PCB_LAYER_ID sequence[] = {
  136. F_Cu,
  137. In1_Cu,
  138. In2_Cu,
  139. In3_Cu,
  140. In4_Cu,
  141. In5_Cu,
  142. In6_Cu,
  143. In7_Cu,
  144. In8_Cu,
  145. In9_Cu,
  146. In10_Cu,
  147. In11_Cu,
  148. In12_Cu,
  149. In13_Cu,
  150. In14_Cu,
  151. In15_Cu,
  152. In16_Cu,
  153. In17_Cu,
  154. In18_Cu,
  155. In19_Cu,
  156. In20_Cu,
  157. In21_Cu,
  158. In22_Cu,
  159. In23_Cu,
  160. In24_Cu,
  161. In25_Cu,
  162. In26_Cu,
  163. In27_Cu,
  164. In28_Cu,
  165. In29_Cu,
  166. In30_Cu,
  167. B_Cu, // 31
  168. };
  169. return Seq( sequence, arrayDim( sequence ) );
  170. }
  171. LSEQ LSET::Technicals( LSET aSetToOmit ) const
  172. {
  173. // desired sequence
  174. static const PCB_LAYER_ID sequence[] = {
  175. F_Adhes,
  176. B_Adhes,
  177. F_Paste,
  178. B_Paste,
  179. F_SilkS,
  180. B_SilkS,
  181. F_Mask,
  182. B_Mask,
  183. F_CrtYd,
  184. B_CrtYd,
  185. F_Fab,
  186. B_Fab,
  187. };
  188. LSET subset = ~aSetToOmit & *this;
  189. return subset.Seq( sequence, arrayDim( sequence ) );
  190. }
  191. LSEQ LSET::Users() const
  192. {
  193. // desired
  194. static const PCB_LAYER_ID sequence[] = {
  195. Dwgs_User,
  196. Cmts_User,
  197. Eco1_User,
  198. Eco2_User,
  199. Edge_Cuts,
  200. Margin,
  201. User_1,
  202. User_2,
  203. User_3,
  204. User_4,
  205. User_5,
  206. User_6,
  207. User_7,
  208. User_8,
  209. User_9
  210. };
  211. return Seq( sequence, arrayDim( sequence ) );
  212. }
  213. LSEQ LSET::TechAndUserUIOrder() const
  214. {
  215. static const PCB_LAYER_ID sequence[] = {
  216. F_Adhes,
  217. B_Adhes,
  218. F_Paste,
  219. B_Paste,
  220. F_SilkS,
  221. B_SilkS,
  222. F_Mask,
  223. B_Mask,
  224. Dwgs_User,
  225. Cmts_User,
  226. Eco1_User,
  227. Eco2_User,
  228. Edge_Cuts,
  229. Margin,
  230. F_CrtYd,
  231. B_CrtYd,
  232. F_Fab,
  233. B_Fab,
  234. User_1,
  235. User_2,
  236. User_3,
  237. User_4,
  238. User_5,
  239. User_6,
  240. User_7,
  241. User_8,
  242. User_9
  243. };
  244. return Seq( sequence, arrayDim( sequence ) );
  245. }
  246. std::string LSET::FmtBin() const
  247. {
  248. std::string ret;
  249. int bit_count = size();
  250. for( int bit=0; bit<bit_count; ++bit )
  251. {
  252. if( bit )
  253. {
  254. if( !( bit % 8 ) )
  255. ret += '|';
  256. else if( !( bit % 4 ) )
  257. ret += '_';
  258. }
  259. ret += (*this)[bit] ? '1' : '0';
  260. }
  261. // reverse of string
  262. return std::string( ret.rbegin(), ret.rend() );
  263. }
  264. std::string LSET::FmtHex() const
  265. {
  266. std::string ret;
  267. static const char hex[] = "0123456789abcdef";
  268. size_t nibble_count = ( size() + 3 ) / 4;
  269. for( size_t nibble = 0; nibble < nibble_count; ++nibble )
  270. {
  271. unsigned int ndx = 0;
  272. // test 4 consecutive bits and set ndx to 0-15
  273. for( size_t nibble_bit = 0; nibble_bit < 4; ++nibble_bit )
  274. {
  275. size_t nibble_pos = nibble_bit + ( nibble * 4 );
  276. // make sure it's not extra bits that don't exist in the bitset but need to in the
  277. // hex format
  278. if( nibble_pos >= size() )
  279. break;
  280. if( ( *this )[nibble_pos] )
  281. ndx |= ( 1 << nibble_bit );
  282. }
  283. if( nibble && !( nibble % 8 ) )
  284. ret += '_';
  285. assert( ndx < arrayDim( hex ) );
  286. ret += hex[ndx];
  287. }
  288. // reverse of string
  289. return std::string( ret.rbegin(), ret.rend() );
  290. }
  291. int LSET::ParseHex( const char* aStart, int aCount )
  292. {
  293. LSET tmp;
  294. const char* rstart = aStart + aCount - 1;
  295. const char* rend = aStart - 1;
  296. const int bitcount = size();
  297. int nibble_ndx = 0;
  298. while( rstart > rend )
  299. {
  300. int cc = *rstart--;
  301. if( cc == '_' )
  302. continue;
  303. int nibble;
  304. if( cc >= '0' && cc <= '9' )
  305. nibble = cc - '0';
  306. else if( cc >= 'a' && cc <= 'f' )
  307. nibble = cc - 'a' + 10;
  308. else if( cc >= 'A' && cc <= 'F' )
  309. nibble = cc - 'A' + 10;
  310. else
  311. break;
  312. int bit = nibble_ndx * 4;
  313. for( int ndx=0; bit<bitcount && ndx<4; ++bit, ++ndx )
  314. if( nibble & (1<<ndx) )
  315. tmp.set( bit );
  316. if( bit >= bitcount )
  317. break;
  318. ++nibble_ndx;
  319. }
  320. int byte_count = aStart + aCount - 1 - rstart;
  321. assert( byte_count >= 0 );
  322. if( byte_count > 0 )
  323. *this = tmp;
  324. return byte_count;
  325. }
  326. LSEQ LSET::Seq( const PCB_LAYER_ID* aWishListSequence, unsigned aCount ) const
  327. {
  328. LSEQ ret;
  329. #if defined(DEBUG) && 0
  330. LSET dup_detector;
  331. for( unsigned i=0; i<aCount; ++i )
  332. {
  333. PCB_LAYER_ID id = aWishListSequence[i];
  334. if( test( id ) )
  335. {
  336. wxASSERT_MSG( !dup_detector[id], wxT( "Duplicate in aWishListSequence" ) );
  337. dup_detector[id] = true;
  338. ret.push_back( id );
  339. }
  340. }
  341. #else
  342. for( unsigned i=0; i<aCount; ++i )
  343. {
  344. PCB_LAYER_ID id = aWishListSequence[i];
  345. if( test( id ) )
  346. ret.push_back( id );
  347. }
  348. #endif
  349. return ret;
  350. }
  351. LSEQ LSET::Seq( const LSEQ& aSequence ) const
  352. {
  353. LSEQ ret;
  354. for( PCB_LAYER_ID layer : aSequence )
  355. {
  356. if( test( layer ) )
  357. ret.push_back( layer );
  358. }
  359. return ret;
  360. }
  361. LSEQ LSET::Seq() const
  362. {
  363. LSEQ ret;
  364. ret.reserve( size() );
  365. for( unsigned i = 0; i < size(); ++i )
  366. {
  367. if( test( i ) )
  368. ret.push_back( PCB_LAYER_ID( i ) );
  369. }
  370. return ret;
  371. }
  372. LSEQ LSET::SeqStackupTop2Bottom( PCB_LAYER_ID aSelectedLayer ) const
  373. {
  374. static const PCB_LAYER_ID sequence[] = {
  375. Edge_Cuts,
  376. Margin,
  377. Dwgs_User,
  378. Cmts_User,
  379. Eco1_User,
  380. Eco2_User,
  381. User_1,
  382. User_2,
  383. User_3,
  384. User_4,
  385. User_5,
  386. User_6,
  387. User_7,
  388. User_8,
  389. User_9,
  390. F_Fab,
  391. F_SilkS,
  392. F_Paste,
  393. F_Adhes,
  394. F_Mask,
  395. F_CrtYd,
  396. F_Cu,
  397. In1_Cu,
  398. In2_Cu,
  399. In3_Cu,
  400. In4_Cu,
  401. In5_Cu,
  402. In6_Cu,
  403. In7_Cu,
  404. In8_Cu,
  405. In9_Cu,
  406. In10_Cu,
  407. In11_Cu,
  408. In12_Cu,
  409. In13_Cu,
  410. In14_Cu,
  411. In15_Cu,
  412. In16_Cu,
  413. In17_Cu,
  414. In18_Cu,
  415. In19_Cu,
  416. In20_Cu,
  417. In21_Cu,
  418. In22_Cu,
  419. In23_Cu,
  420. In24_Cu,
  421. In25_Cu,
  422. In26_Cu,
  423. In27_Cu,
  424. In28_Cu,
  425. In29_Cu,
  426. In30_Cu,
  427. B_Cu,
  428. B_CrtYd,
  429. B_Mask,
  430. B_Adhes,
  431. B_Paste,
  432. B_SilkS,
  433. B_Fab,
  434. };
  435. LSEQ seq = Seq( sequence, arrayDim( sequence ) );
  436. if( aSelectedLayer != UNDEFINED_LAYER )
  437. {
  438. auto it = std::find( seq.begin(), seq.end(), aSelectedLayer );
  439. if( it != seq.end() )
  440. {
  441. seq.erase( it );
  442. seq.insert( seq.begin(), aSelectedLayer );
  443. }
  444. }
  445. return seq;
  446. }
  447. LSEQ LSET::SeqStackupForPlotting() const
  448. {
  449. // bottom-to-top stack-up layers
  450. // Note that the bottom technical layers are flipped so that when plotting a bottom-side view,
  451. // they appear in the correct sequence.
  452. static const PCB_LAYER_ID sequence[] = {
  453. B_Cu,
  454. B_Mask,
  455. B_Paste,
  456. B_SilkS,
  457. B_Adhes,
  458. B_CrtYd,
  459. B_Fab,
  460. In30_Cu,
  461. In29_Cu,
  462. In28_Cu,
  463. In27_Cu,
  464. In26_Cu,
  465. In25_Cu,
  466. In24_Cu,
  467. In23_Cu,
  468. In22_Cu,
  469. In21_Cu,
  470. In20_Cu,
  471. In19_Cu,
  472. In18_Cu,
  473. In17_Cu,
  474. In16_Cu,
  475. In15_Cu,
  476. In14_Cu,
  477. In13_Cu,
  478. In12_Cu,
  479. In11_Cu,
  480. In10_Cu,
  481. In9_Cu,
  482. In8_Cu,
  483. In7_Cu,
  484. In6_Cu,
  485. In5_Cu,
  486. In4_Cu,
  487. In3_Cu,
  488. In2_Cu,
  489. In1_Cu,
  490. F_Cu,
  491. F_Mask,
  492. F_Paste,
  493. F_SilkS,
  494. F_Adhes,
  495. F_CrtYd,
  496. F_Fab,
  497. Dwgs_User,
  498. Cmts_User,
  499. Eco1_User,
  500. Eco2_User,
  501. User_1,
  502. User_2,
  503. User_3,
  504. User_4,
  505. User_5,
  506. User_6,
  507. User_7,
  508. User_8,
  509. User_9,
  510. Margin,
  511. Edge_Cuts,
  512. };
  513. return Seq( sequence, arrayDim( sequence ) );
  514. }
  515. LSET& LSET::Flip( int aCopperLayersCount )
  516. {
  517. LSET oldMask = *this;
  518. reset();
  519. if( oldMask.test( B_Cu ) )
  520. set( F_Cu );
  521. if( oldMask.test( F_Cu ) )
  522. set( B_Cu );
  523. if( oldMask.test( B_SilkS ) )
  524. set( F_SilkS );
  525. if( oldMask.test( F_SilkS ) )
  526. set( B_SilkS );
  527. if( oldMask.test( B_Adhes ) )
  528. set( F_Adhes );
  529. if( oldMask.test( F_Adhes ) )
  530. set( B_Adhes );
  531. if( oldMask.test( B_Mask ) )
  532. set( F_Mask );
  533. if( oldMask.test( F_Mask ) )
  534. set( B_Mask );
  535. if( oldMask.test( B_Paste ) )
  536. set( F_Paste );
  537. if( oldMask.test( F_Paste ) )
  538. set( B_Paste );
  539. if( oldMask.test( B_Adhes ) )
  540. set( F_Adhes );
  541. if( oldMask.test( F_Adhes ) )
  542. set( B_Adhes );
  543. if( oldMask.test( B_CrtYd ) )
  544. set( F_CrtYd );
  545. if( oldMask.test( F_CrtYd ) )
  546. set( B_CrtYd );
  547. if( oldMask.test( B_Fab ) )
  548. set( F_Fab );
  549. if( oldMask.test( F_Fab ) )
  550. set( B_Fab );
  551. if( aCopperLayersCount >= 4 ) // Internal layers exist
  552. {
  553. LSET internalMask = oldMask & InternalCuMask();
  554. int innerLayerCnt = aCopperLayersCount - 2;
  555. // the flipped mask is the innerLayerCnt bits rewritten in reverse order
  556. // ( bits innerLayerCnt to 1 rewritten in bits 1 to innerLayerCnt )
  557. for( int ii = 0; ii < innerLayerCnt; ii++ )
  558. {
  559. if( internalMask[innerLayerCnt - ii] )
  560. {
  561. set( ii + In1_Cu );
  562. }
  563. else
  564. {
  565. reset( ii + In1_Cu );
  566. }
  567. }
  568. }
  569. return *this;
  570. }
  571. PCB_LAYER_ID LSET::ExtractLayer() const
  572. {
  573. unsigned set_count = count();
  574. if( !set_count )
  575. return UNSELECTED_LAYER;
  576. else if( set_count > 1 )
  577. return UNDEFINED_LAYER;
  578. for( unsigned i=0; i < size(); ++i )
  579. {
  580. if( test( i ) )
  581. return PCB_LAYER_ID( i );
  582. }
  583. wxASSERT( 0 ); // set_count was verified as 1 above, what did you break?
  584. return UNDEFINED_LAYER;
  585. }
  586. LSET LSET::FrontAssembly()
  587. {
  588. static const LSET saved( { F_SilkS, F_Mask, F_Fab, F_CrtYd } );
  589. return saved;
  590. }
  591. LSET LSET::BackAssembly()
  592. {
  593. static const LSET saved( { B_SilkS, B_Mask, B_Fab, B_CrtYd } );
  594. return saved;
  595. }
  596. LSET LSET::InternalCuMask()
  597. {
  598. static const LSET saved( { In1_Cu, In2_Cu, In3_Cu, In4_Cu, In5_Cu, In6_Cu,
  599. In7_Cu, In8_Cu, In9_Cu, In10_Cu, In11_Cu, In12_Cu,
  600. In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu,
  601. In19_Cu, In20_Cu, In21_Cu, In22_Cu, In23_Cu, In24_Cu,
  602. In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In30_Cu } );
  603. return saved;
  604. }
  605. LSET LSET::AllCuMask( int aCuLayerCount )
  606. {
  607. // retain all in static as the full set, which is a common case.
  608. static const LSET all = InternalCuMask().set( F_Cu ).set( B_Cu );
  609. if( aCuLayerCount == MAX_CU_LAYERS )
  610. return all;
  611. // subtract out some Cu layers not wanted in the mask.
  612. LSET ret = all;
  613. int clear_count = MAX_CU_LAYERS - aCuLayerCount;
  614. clear_count = std::clamp( clear_count, 0, MAX_CU_LAYERS - 2 );
  615. for( int elem = In30_Cu; clear_count; --elem, --clear_count )
  616. ret.set( elem, false );
  617. return ret;
  618. }
  619. LSET LSET::AllNonCuMask()
  620. {
  621. static const LSET saved = LSET().set() & ~AllCuMask();
  622. return saved;
  623. }
  624. LSET LSET::ExternalCuMask()
  625. {
  626. static const LSET saved( { F_Cu, B_Cu } );
  627. return saved;
  628. }
  629. LSET LSET::AllLayersMask()
  630. {
  631. static const LSET saved = LSET().set();
  632. return saved;
  633. }
  634. LSET LSET::BackTechMask()
  635. {
  636. static const LSET saved( { B_SilkS, B_Mask, B_Adhes, B_Paste, B_CrtYd, B_Fab } );
  637. return saved;
  638. }
  639. LSET LSET::BackBoardTechMask()
  640. {
  641. static const LSET saved( { B_SilkS, B_Mask, B_Adhes, B_Paste } );
  642. return saved;
  643. }
  644. LSET LSET::FrontTechMask()
  645. {
  646. static const LSET saved( { F_SilkS, F_Mask, F_Adhes, F_Paste, F_CrtYd, F_Fab } );
  647. return saved;
  648. }
  649. LSET LSET::FrontBoardTechMask()
  650. {
  651. static const LSET saved( { F_SilkS, F_Mask, F_Adhes, F_Paste } );
  652. return saved;
  653. }
  654. LSET LSET::AllTechMask()
  655. {
  656. static const LSET saved = BackTechMask() | FrontTechMask();
  657. return saved;
  658. }
  659. LSET LSET::AllBoardTechMask()
  660. {
  661. static const LSET saved = BackBoardTechMask() | FrontBoardTechMask();
  662. return saved;
  663. }
  664. LSET LSET::UserMask()
  665. {
  666. static const LSET saved( { Dwgs_User, Cmts_User, Eco1_User, Eco2_User, Edge_Cuts, Margin } );
  667. return saved;
  668. }
  669. LSET LSET::PhysicalLayersMask()
  670. {
  671. static const LSET saved = AllBoardTechMask() | AllCuMask();
  672. return saved;
  673. }
  674. LSET LSET::UserDefinedLayers()
  675. {
  676. static const LSET saved(
  677. { User_1, User_2, User_3, User_4, User_5, User_6, User_7, User_8, User_9 } );
  678. return saved;
  679. }
  680. LSET LSET::FrontMask()
  681. {
  682. static const LSET saved = FrontTechMask().set( F_Cu );
  683. return saved;
  684. }
  685. LSET LSET::BackMask()
  686. {
  687. static const LSET saved = BackTechMask().set( B_Cu );
  688. return saved;
  689. }
  690. LSET LSET::SideSpecificMask()
  691. {
  692. static const LSET saved = BackTechMask() | FrontTechMask() | AllCuMask();
  693. return saved;
  694. }
  695. LSET LSET::ForbiddenFootprintLayers()
  696. {
  697. static const LSET saved = InternalCuMask();
  698. return saved;
  699. }
  700. LSEQ LSET::UIOrder() const
  701. {
  702. LSEQ order = CuStack();
  703. LSEQ techuser = TechAndUserUIOrder();
  704. order.insert( order.end(), techuser.begin(), techuser.end() );
  705. return order;
  706. }
  707. PCB_LAYER_ID ToLAYER_ID( int aLayer )
  708. {
  709. wxASSERT( aLayer < GAL_LAYER_ID_END );
  710. return PCB_LAYER_ID( aLayer );
  711. }
  712. GAL_SET::GAL_SET( const GAL_LAYER_ID* aArray, unsigned aCount ) : GAL_SET()
  713. {
  714. for( unsigned i = 0; i < aCount; ++i )
  715. set( aArray[i] );
  716. }
  717. std::vector<GAL_LAYER_ID> GAL_SET::Seq() const
  718. {
  719. std::vector<GAL_LAYER_ID> ret;
  720. for( size_t i = 0; i < size(); ++i )
  721. {
  722. if( test( i ) )
  723. ret.push_back( static_cast<GAL_LAYER_ID>( i + GAL_LAYER_ID_START ) );
  724. }
  725. return ret;
  726. }
  727. GAL_SET GAL_SET::DefaultVisible()
  728. {
  729. static const GAL_LAYER_ID visible[] = {
  730. LAYER_VIAS,
  731. LAYER_VIA_MICROVIA,
  732. LAYER_VIA_BBLIND,
  733. LAYER_VIA_THROUGH,
  734. // LAYER_HIDDEN_TEXT, // Invisible text hidden by default
  735. LAYER_ANCHOR,
  736. LAYER_PADS_SMD_FR,
  737. LAYER_PADS_SMD_BK,
  738. LAYER_RATSNEST,
  739. LAYER_GRID,
  740. LAYER_GRID_AXES,
  741. LAYER_FOOTPRINTS_FR,
  742. LAYER_FOOTPRINTS_BK,
  743. LAYER_FP_TEXT,
  744. LAYER_FP_VALUES,
  745. LAYER_FP_REFERENCES,
  746. LAYER_TRACKS,
  747. LAYER_PADS_TH,
  748. LAYER_PAD_PLATEDHOLES,
  749. LAYER_NON_PLATEDHOLES,
  750. LAYER_PAD_HOLEWALLS,
  751. LAYER_VIA_HOLES,
  752. LAYER_VIA_HOLEWALLS,
  753. LAYER_DRC_ERROR,
  754. LAYER_DRC_WARNING,
  755. // LAYER_DRC_EXCLUSION, // DRC exclusions hidden by default
  756. LAYER_DRAWINGSHEET,
  757. LAYER_GP_OVERLAY,
  758. LAYER_SELECT_OVERLAY,
  759. LAYER_PCB_BACKGROUND,
  760. LAYER_CURSOR,
  761. LAYER_AUX_ITEMS,
  762. LAYER_DRAW_BITMAPS,
  763. LAYER_PADS,
  764. LAYER_ZONES,
  765. LAYER_SHAPES,
  766. LAYER_LOCKED_ITEM_SHADOW,
  767. LAYER_CONFLICTS_SHADOW
  768. };
  769. static const GAL_SET saved( visible, arrayDim( visible ) );
  770. return saved;
  771. }