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.

873 lines
20 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
1 year ago
1 year ago
1 year 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 The 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 <map>
  31. #include <core/arraydim.h>
  32. #include <layer_ids.h> // for PCB_LAYER_ID
  33. #include <layer_range.h>
  34. #include <lseq.h>
  35. #include <macros.h> // for arrayDim
  36. #include <wx/debug.h> // for wxASSERT, wxASSERT_MSG
  37. #include <wx/string.h>
  38. #include <lset.h>
  39. LSET::LSET( std::initializer_list<PCB_LAYER_ID> aList ) :
  40. LSET()
  41. {
  42. for( PCB_LAYER_ID layer : aList )
  43. {
  44. if( layer >= 0 )
  45. set( layer );
  46. }
  47. }
  48. LSET::LSET( const std::vector<PCB_LAYER_ID>& aList ) :
  49. LSET()
  50. {
  51. for( PCB_LAYER_ID layer : aList )
  52. {
  53. if( layer >= 0 )
  54. set( layer );
  55. }
  56. }
  57. LSET::LSET( const LSEQ& aSeq ) :
  58. LSET()
  59. {
  60. for( PCB_LAYER_ID layer : aSeq )
  61. {
  62. if( layer >= 0 )
  63. set( layer );
  64. }
  65. }
  66. LSET::LSET( const LAYER_RANGE& aRange )
  67. {
  68. for( PCB_LAYER_ID layer : aRange )
  69. {
  70. if( layer >= 0 )
  71. set( layer );
  72. }
  73. }
  74. int LSET::LayerCount( PCB_LAYER_ID aStart, PCB_LAYER_ID aEnd, int aCopperLayerCount )
  75. {
  76. int start = aStart;
  77. int end = aEnd;
  78. // Both layers need to be copper
  79. wxCHECK( IsCopperLayer( aStart ) && IsCopperLayer( aEnd ), aCopperLayerCount );
  80. if( aStart == B_Cu )
  81. std::swap( start, end );
  82. if( aStart == aEnd )
  83. return 1;
  84. if( aStart == F_Cu )
  85. {
  86. if ( aEnd == B_Cu )
  87. return aCopperLayerCount;
  88. else
  89. return ( end - start ) / 2 - 1;
  90. }
  91. else if ( aEnd == B_Cu )
  92. {
  93. // Add 1 for the B_Cu layer
  94. return aCopperLayerCount - start / 2 + 1;
  95. }
  96. return ( end - start ) / 2;
  97. }
  98. int LSET::NameToLayer( wxString& aName )
  99. {
  100. std::map<wxString, PCB_LAYER_ID> layerMap = {
  101. { "F.Cu", F_Cu },
  102. { "B.Cu", B_Cu },
  103. { "F.Adhes", F_Adhes },
  104. { "B.Adhes", B_Adhes },
  105. { "F.Paste", F_Paste },
  106. { "B.Paste", B_Paste },
  107. { "F.SilkS", F_SilkS },
  108. { "B.SilkS", B_SilkS },
  109. { "F.Mask", F_Mask },
  110. { "B.Mask", B_Mask },
  111. { "Dwgs.User", Dwgs_User },
  112. { "Cmts.User", Cmts_User },
  113. { "Eco1.User", Eco1_User },
  114. { "Eco2.User", Eco2_User },
  115. { "Edge.Cuts", Edge_Cuts },
  116. { "Margin", Margin },
  117. { "F.CrtYd", F_CrtYd },
  118. { "B.CrtYd", B_CrtYd },
  119. { "F.Fab", F_Fab },
  120. { "B.Fab", B_Fab },
  121. { "Rescue", Rescue },
  122. { "B.Cu", B_Cu },
  123. };
  124. if( auto it = layerMap.find( aName ); it != layerMap.end() )
  125. return static_cast<int>( it->second );
  126. if( aName.StartsWith( "User." ) )
  127. {
  128. long offset;
  129. if( aName.Mid( 5 ).ToLong( &offset ) && offset > 0 )
  130. return static_cast<int>( User_1 ) + ( offset - 1 ) * 2;
  131. }
  132. if( aName.StartsWith( "In" ) )
  133. {
  134. long offset;
  135. wxString str_num = aName.Mid( 2 );
  136. str_num.RemoveLast( 3 ); // Removes .Cu
  137. if( str_num.ToLong( &offset ) && offset > 0 )
  138. return static_cast<int>( In1_Cu ) + ( offset - 1 ) * 2;
  139. }
  140. return -1;
  141. }
  142. bool LSET::IsBetween( PCB_LAYER_ID aStart, PCB_LAYER_ID aEnd, PCB_LAYER_ID aLayer )
  143. {
  144. if( aLayer == aStart || aLayer == aEnd )
  145. return true;
  146. int start = std::min( aStart, aEnd );
  147. int end = std::max( aStart, aEnd );
  148. int layer = aLayer;
  149. if( end == B_Cu )
  150. {
  151. //Reassign the end layer to the largest possible positive even number
  152. end = std::numeric_limits<PCB_LAYER_ID>::max() & ~1;
  153. }
  154. return !( layer & 1 ) && ( layer >= start ) && ( layer <= end );
  155. }
  156. /**
  157. * NOTE: These names must not be translated or changed. They are used as tokens in the board
  158. * file format because the ordinal value of the PCB_LAYER_ID enum was not stable over time.
  159. * @see LayerName() for what should be used to display the default name of a layer in the GUI.
  160. */
  161. wxString LSET::Name( PCB_LAYER_ID aLayerId )
  162. {
  163. wxString txt;
  164. // using a switch to explicitly show the mapping more clearly
  165. switch( aLayerId )
  166. {
  167. case F_Cu: txt = wxT( "F.Cu" ); break;
  168. case B_Cu: txt = wxT( "B.Cu" ); break;
  169. // Technicals
  170. case B_Adhes: txt = wxT( "B.Adhes" ); break;
  171. case F_Adhes: txt = wxT( "F.Adhes" ); break;
  172. case B_Paste: txt = wxT( "B.Paste" ); break;
  173. case F_Paste: txt = wxT( "F.Paste" ); break;
  174. case B_SilkS: txt = wxT( "B.SilkS" ); break;
  175. case F_SilkS: txt = wxT( "F.SilkS" ); break;
  176. case B_Mask: txt = wxT( "B.Mask" ); break;
  177. case F_Mask: txt = wxT( "F.Mask" ); break;
  178. // Users
  179. case Dwgs_User: txt = wxT( "Dwgs.User" ); break;
  180. case Cmts_User: txt = wxT( "Cmts.User" ); break;
  181. case Eco1_User: txt = wxT( "Eco1.User" ); break;
  182. case Eco2_User: txt = wxT( "Eco2.User" ); break;
  183. case Edge_Cuts: txt = wxT( "Edge.Cuts" ); break;
  184. case Margin: txt = wxT( "Margin" ); break;
  185. // Footprint
  186. case F_CrtYd: txt = wxT( "F.CrtYd" ); break;
  187. case B_CrtYd: txt = wxT( "B.CrtYd" ); break;
  188. case F_Fab: txt = wxT( "F.Fab" ); break;
  189. case B_Fab: txt = wxT( "B.Fab" ); break;
  190. // Rescue
  191. case Rescue: txt = wxT( "Rescue" ); break;
  192. default:
  193. if( static_cast<int>( aLayerId ) & 1 )
  194. {
  195. int offset = ( aLayerId - Rescue ) / 2;
  196. txt = wxString::Format( wxT( "User.%d" ), offset );
  197. }
  198. else
  199. {
  200. int offset = ( aLayerId - B_Cu ) / 2;
  201. txt = wxString::Format( wxT( "In%d.Cu" ), offset );
  202. }
  203. }
  204. return txt;
  205. }
  206. LSEQ LSET::CuStack() const
  207. {
  208. LSEQ ret;
  209. ret.reserve( 32 );
  210. for( auto it = copper_layers_begin(); it != copper_layers_end(); ++it )
  211. ret.push_back( *it );
  212. return ret;
  213. }
  214. LSEQ LSET::TechAndUserUIOrder() const
  215. {
  216. LSEQ ret;
  217. ret.reserve( 32 );
  218. ret = Seq( {
  219. F_Adhes,
  220. B_Adhes,
  221. F_Paste,
  222. B_Paste,
  223. F_SilkS,
  224. B_SilkS,
  225. F_Mask,
  226. B_Mask,
  227. Dwgs_User,
  228. Cmts_User,
  229. Eco1_User,
  230. Eco2_User,
  231. Edge_Cuts,
  232. Margin,
  233. F_CrtYd,
  234. B_CrtYd,
  235. F_Fab,
  236. B_Fab
  237. } );
  238. for( auto it = non_copper_layers_begin(); it != non_copper_layers_end(); ++it )
  239. {
  240. if( *it >= User_1 )
  241. ret.push_back( *it );
  242. }
  243. return ret;
  244. }
  245. LSEQ LSET::Seq( const LSEQ& aSequence ) const
  246. {
  247. LSEQ ret;
  248. for( PCB_LAYER_ID layer : aSequence )
  249. {
  250. if( test( layer ) )
  251. ret.push_back( layer );
  252. }
  253. return ret;
  254. }
  255. LSEQ LSET::Seq() const
  256. {
  257. LSEQ ret;
  258. ret.reserve( size() );
  259. for( unsigned i = 0; i < size(); ++i )
  260. {
  261. if( test( i ) )
  262. ret.push_back( PCB_LAYER_ID( i ) );
  263. }
  264. return ret;
  265. }
  266. LSEQ LSET::SeqStackupTop2Bottom( PCB_LAYER_ID aSelectedLayer ) const
  267. {
  268. LSEQ base_sequence = Seq( {
  269. Edge_Cuts,
  270. Margin,
  271. Dwgs_User,
  272. Cmts_User,
  273. Eco1_User,
  274. Eco2_User
  275. } );
  276. LSEQ top_tech_sequence = Seq( {
  277. F_Fab,
  278. F_SilkS,
  279. F_Paste,
  280. F_Adhes,
  281. F_Mask,
  282. F_CrtYd,
  283. } );
  284. LSEQ bottom_tech_sequence = Seq( {
  285. B_CrtYd,
  286. B_Mask,
  287. B_Adhes,
  288. B_Paste,
  289. B_SilkS,
  290. B_Fab,
  291. } );
  292. LSEQ seq = Seq( base_sequence );
  293. for( auto it = non_copper_layers_begin(); it != non_copper_layers_end(); ++it )
  294. {
  295. if( *it >= User_1 )
  296. seq.push_back( *it );
  297. }
  298. std::copy( top_tech_sequence.begin(), top_tech_sequence.end(), std::back_inserter( seq ) );
  299. for( auto it = copper_layers_begin(); it != copper_layers_end(); ++it )
  300. seq.push_back( *it );
  301. std::copy( bottom_tech_sequence.begin(), bottom_tech_sequence.end(), std::back_inserter( seq ) );
  302. if( aSelectedLayer != UNDEFINED_LAYER )
  303. {
  304. auto it = std::find( seq.begin(), seq.end(), aSelectedLayer );
  305. if( it != seq.end() )
  306. {
  307. seq.erase( it );
  308. seq.insert( seq.begin(), aSelectedLayer );
  309. }
  310. }
  311. return seq;
  312. }
  313. LSEQ LSET::SeqStackupForPlotting() const
  314. {
  315. // bottom-to-top stack-up layers
  316. // Note that the bottom technical layers are flipped so that when plotting a bottom-side view,
  317. // they appear in the correct sequence.
  318. LSEQ bottom_tech_sequence = Seq( {
  319. B_Cu,
  320. B_Mask,
  321. B_Paste,
  322. B_SilkS,
  323. B_Adhes,
  324. B_CrtYd,
  325. B_Fab,
  326. } );
  327. // Copper layers go here
  328. LSEQ top_tech_sequence = Seq( {
  329. F_Mask,
  330. F_Paste,
  331. F_SilkS,
  332. F_Adhes,
  333. F_CrtYd,
  334. F_Fab,
  335. } );
  336. LSEQ user_sequence = Seq( {
  337. Dwgs_User,
  338. Cmts_User,
  339. Eco1_User,
  340. Eco2_User,
  341. } );
  342. // User layers go here
  343. LSEQ base_sequence = Seq( {
  344. Margin,
  345. Edge_Cuts,
  346. } );
  347. LSEQ seq = Seq( bottom_tech_sequence );
  348. std::vector<PCB_LAYER_ID> temp_layers;
  349. // We are going to reverse the copper layers and then add them to the sequence
  350. // because the plotting order is bottom-to-top
  351. for( auto it = copper_layers_begin(); it != copper_layers_end(); ++it )
  352. {
  353. // Skip B_Cu because it is already in the sequence (if it exists)
  354. if( *it != B_Cu )
  355. temp_layers.push_back( *it );
  356. }
  357. for( auto it = temp_layers.rbegin(); it != temp_layers.rend(); ++it )
  358. seq.push_back( *it );
  359. std::copy( top_tech_sequence.begin(), top_tech_sequence.end(), std::back_inserter( seq ) );
  360. std::copy( user_sequence.begin(), user_sequence.end(), std::back_inserter( seq ) );
  361. temp_layers.clear();
  362. for( auto it = non_copper_layers_begin(); it != non_copper_layers_end(); ++it )
  363. {
  364. if( *it >= User_1 )
  365. temp_layers.push_back( *it );
  366. }
  367. for( auto it = temp_layers.rbegin(); it != temp_layers.rend(); ++it )
  368. {
  369. seq.push_back( *it );
  370. }
  371. std::copy( base_sequence.begin(), base_sequence.end(), std::back_inserter( seq ) );
  372. return seq;
  373. }
  374. LSET& LSET::Flip( int aCopperLayersCount )
  375. {
  376. LSET oldMask = *this;
  377. reset();
  378. // Mapping for Copper and Non-Copper layers
  379. const std::map<PCB_LAYER_ID, PCB_LAYER_ID> flip_map =
  380. {
  381. {F_Cu, B_Cu},
  382. {B_Cu, F_Cu},
  383. {F_SilkS, B_SilkS},
  384. {B_SilkS, F_SilkS},
  385. {F_Adhes, B_Adhes},
  386. {B_Adhes, F_Adhes},
  387. {F_Mask, B_Mask},
  388. {B_Mask, F_Mask},
  389. {F_Paste, B_Paste},
  390. {B_Paste, F_Paste},
  391. {F_CrtYd, B_CrtYd},
  392. {B_CrtYd, F_CrtYd},
  393. {F_Fab, B_Fab},
  394. {B_Fab, F_Fab}
  395. };
  396. for( const auto& pair : flip_map )
  397. {
  398. if( oldMask.test( pair.first ) )
  399. set( pair.second );
  400. }
  401. if( aCopperLayersCount >= 4 )
  402. {
  403. LSET internalMask = oldMask & InternalCuMask();
  404. int innerLayerCount = aCopperLayersCount - 2;
  405. for( int ii = 1; ii <= innerLayerCount; ii++ )
  406. {
  407. if( internalMask.test( ( innerLayerCount - ii + 1 ) * 2 + B_Cu ) )
  408. {
  409. set( ii * 2 + B_Cu );
  410. }
  411. }
  412. }
  413. return *this;
  414. }
  415. PCB_LAYER_ID LSET::ExtractLayer() const
  416. {
  417. unsigned set_count = count();
  418. if( !set_count )
  419. return UNSELECTED_LAYER;
  420. else if( set_count > 1 )
  421. return UNDEFINED_LAYER;
  422. for( unsigned i=0; i < size(); ++i )
  423. {
  424. if( test( i ) )
  425. return PCB_LAYER_ID( i );
  426. }
  427. wxASSERT( 0 ); // set_count was verified as 1 above, what did you break?
  428. return UNDEFINED_LAYER;
  429. }
  430. LSET LSET::FrontAssembly()
  431. {
  432. static const LSET saved( { F_SilkS, F_Mask, F_Fab, F_CrtYd } );
  433. return saved;
  434. }
  435. LSET LSET::BackAssembly()
  436. {
  437. static const LSET saved( { B_SilkS, B_Mask, B_Fab, B_CrtYd } );
  438. return saved;
  439. }
  440. LSET LSET::InternalCuMask()
  441. {
  442. static const LSET saved( { In1_Cu, In2_Cu, In3_Cu, In4_Cu, In5_Cu, In6_Cu,
  443. In7_Cu, In8_Cu, In9_Cu, In10_Cu, In11_Cu, In12_Cu,
  444. In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu,
  445. In19_Cu, In20_Cu, In21_Cu, In22_Cu, In23_Cu, In24_Cu,
  446. In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In30_Cu } );
  447. return saved;
  448. }
  449. LSET LSET::AllCuMask( int aCuLayerCount )
  450. {
  451. LSET ret;
  452. for( PCB_LAYER_ID layer : LAYER_RANGE( F_Cu, B_Cu, aCuLayerCount ) )
  453. ret.set( layer );
  454. return ret;
  455. }
  456. LSET LSET::AllNonCuMask()
  457. {
  458. static const LSET saved = LSET().set() & ~AllCuMask();
  459. return saved;
  460. }
  461. LSET LSET::ExternalCuMask()
  462. {
  463. static const LSET saved( { F_Cu, B_Cu } );
  464. return saved;
  465. }
  466. LSET LSET::AllLayersMask()
  467. {
  468. static const LSET saved = LSET().set();
  469. return saved;
  470. }
  471. LSET LSET::BackTechMask()
  472. {
  473. static const LSET saved( { B_SilkS, B_Mask, B_Adhes, B_Paste, B_CrtYd, B_Fab } );
  474. return saved;
  475. }
  476. LSET LSET::BackBoardTechMask()
  477. {
  478. static const LSET saved( { B_SilkS, B_Mask, B_Adhes, B_Paste } );
  479. return saved;
  480. }
  481. LSET LSET::FrontTechMask()
  482. {
  483. static const LSET saved( { F_SilkS, F_Mask, F_Adhes, F_Paste, F_CrtYd, F_Fab } );
  484. return saved;
  485. }
  486. LSET LSET::FrontBoardTechMask()
  487. {
  488. static const LSET saved( { F_SilkS, F_Mask, F_Adhes, F_Paste } );
  489. return saved;
  490. }
  491. LSET LSET::AllTechMask()
  492. {
  493. static const LSET saved = BackTechMask() | FrontTechMask();
  494. return saved;
  495. }
  496. LSET LSET::AllBoardTechMask()
  497. {
  498. static const LSET saved = BackBoardTechMask() | FrontBoardTechMask();
  499. return saved;
  500. }
  501. LSET LSET::UserMask()
  502. {
  503. static const LSET saved( { Dwgs_User, Cmts_User, Eco1_User, Eco2_User, Edge_Cuts, Margin } );
  504. return saved;
  505. }
  506. LSET LSET::PhysicalLayersMask()
  507. {
  508. static const LSET saved = AllBoardTechMask() | AllCuMask();
  509. return saved;
  510. }
  511. LSET LSET::UserDefinedLayers()
  512. {
  513. static const LSET saved(
  514. { User_1, User_2, User_3, User_4, User_5, User_6, User_7, User_8, User_9 } );
  515. return saved;
  516. }
  517. LSET LSET::FrontMask()
  518. {
  519. static const LSET saved = FrontTechMask().set( F_Cu );
  520. return saved;
  521. }
  522. LSET LSET::BackMask()
  523. {
  524. static const LSET saved = BackTechMask().set( B_Cu );
  525. return saved;
  526. }
  527. LSET LSET::SideSpecificMask()
  528. {
  529. static const LSET saved = BackTechMask() | FrontTechMask() | AllCuMask();
  530. return saved;
  531. }
  532. LSET LSET::ForbiddenFootprintLayers()
  533. {
  534. static const LSET saved = InternalCuMask();
  535. return saved;
  536. }
  537. LSEQ LSET::UIOrder() const
  538. {
  539. LSEQ order = CuStack();
  540. LSEQ techuser = TechAndUserUIOrder();
  541. order.insert( order.end(), techuser.begin(), techuser.end() );
  542. return order;
  543. }
  544. PCB_LAYER_ID ToLAYER_ID( int aLayer )
  545. {
  546. // We use std::numeric_limits<int>::max() to represent B_Cu for the connectivity_rtree
  547. if( aLayer == std::numeric_limits<int>::max() )
  548. return B_Cu;
  549. wxASSERT( aLayer < GAL_LAYER_ID_END );
  550. return PCB_LAYER_ID( aLayer );
  551. }
  552. GAL_SET::GAL_SET( const GAL_LAYER_ID* aArray, unsigned aCount ) : GAL_SET()
  553. {
  554. for( unsigned i = 0; i < aCount; ++i )
  555. set( aArray[i] );
  556. }
  557. std::vector<GAL_LAYER_ID> GAL_SET::Seq() const
  558. {
  559. std::vector<GAL_LAYER_ID> ret;
  560. for( size_t i = 0; i < size(); ++i )
  561. {
  562. if( test( i ) )
  563. ret.push_back( static_cast<GAL_LAYER_ID>( i + GAL_LAYER_ID_START ) );
  564. }
  565. return ret;
  566. }
  567. GAL_SET GAL_SET::DefaultVisible()
  568. {
  569. static const GAL_LAYER_ID visible[] = {
  570. LAYER_VIAS,
  571. LAYER_VIA_MICROVIA,
  572. LAYER_VIA_BBLIND,
  573. LAYER_VIA_THROUGH,
  574. // LAYER_HIDDEN_TEXT, // DEPCREATED SINCE 9.0. Invisible text hidden by default
  575. LAYER_ANCHOR,
  576. LAYER_RATSNEST,
  577. LAYER_GRID,
  578. LAYER_GRID_AXES,
  579. LAYER_FOOTPRINTS_FR,
  580. LAYER_FOOTPRINTS_BK,
  581. LAYER_FP_TEXT,
  582. LAYER_FP_VALUES,
  583. LAYER_FP_REFERENCES,
  584. LAYER_TRACKS,
  585. LAYER_PAD_PLATEDHOLES,
  586. LAYER_NON_PLATEDHOLES,
  587. LAYER_PAD_HOLEWALLS,
  588. LAYER_VIA_HOLES,
  589. LAYER_VIA_HOLEWALLS,
  590. LAYER_DRC_ERROR,
  591. LAYER_DRC_WARNING,
  592. LAYER_DRC_SHAPE1,
  593. LAYER_DRC_SHAPE2,
  594. // LAYER_DRC_EXCLUSION, // DRC exclusions hidden by default
  595. LAYER_DRAWINGSHEET,
  596. LAYER_GP_OVERLAY,
  597. LAYER_SELECT_OVERLAY,
  598. LAYER_PCB_BACKGROUND,
  599. LAYER_CURSOR,
  600. LAYER_AUX_ITEMS,
  601. LAYER_DRAW_BITMAPS,
  602. LAYER_PADS,
  603. LAYER_ZONES,
  604. LAYER_SHAPES,
  605. LAYER_LOCKED_ITEM_SHADOW,
  606. LAYER_CONFLICTS_SHADOW
  607. };
  608. static const GAL_SET saved( visible, arrayDim( visible ) );
  609. return saved;
  610. }
  611. #ifndef SWIG // Skip SWIG generators for the iterators because it requires a default constructor
  612. // Custom iterators for Copper and Non-Copper layers
  613. LSET::copper_layers_iterator::copper_layers_iterator( const BASE_SET& set, size_t index ) :
  614. BASE_SET::set_bits_iterator( set, index )
  615. {
  616. m_index = ( index + 1 ) & ~1;
  617. advance_to_next_set_copper_bit();
  618. }
  619. PCB_LAYER_ID LSET::copper_layers_iterator::operator*() const
  620. {
  621. return static_cast<PCB_LAYER_ID>( m_index );
  622. }
  623. LSET::copper_layers_iterator& LSET::copper_layers_iterator::operator++()
  624. {
  625. next_copper_layer();
  626. advance_to_next_set_copper_bit();
  627. return *this;
  628. }
  629. void LSET::copper_layers_iterator::next_copper_layer()
  630. {
  631. if( m_index == F_Cu )
  632. {
  633. m_index += 4;
  634. }
  635. else if( m_index == B_Cu )
  636. {
  637. m_index = m_baseSet.size();
  638. return;
  639. }
  640. else
  641. {
  642. m_index += 2;
  643. if( m_index >= m_baseSet.size() )
  644. m_index = B_Cu;
  645. }
  646. }
  647. void LSET::copper_layers_iterator::advance_to_next_set_copper_bit()
  648. {
  649. while( m_index < m_baseSet.size() && !m_baseSet.test( m_index ) )
  650. next_copper_layer();
  651. }
  652. LSET::non_copper_layers_iterator::non_copper_layers_iterator( const BASE_SET& set, size_t index ) :
  653. BASE_SET::set_bits_iterator( set, index )
  654. {
  655. advance_to_next_set_non_copper_bit();
  656. }
  657. PCB_LAYER_ID LSET::non_copper_layers_iterator::operator*() const
  658. {
  659. return static_cast<PCB_LAYER_ID>( m_index );
  660. }
  661. LSET::non_copper_layers_iterator& LSET::non_copper_layers_iterator::operator++()
  662. {
  663. ++m_index;
  664. advance_to_next_set_non_copper_bit();
  665. return *this;
  666. }
  667. void LSET::non_copper_layers_iterator::advance_to_next_set_non_copper_bit()
  668. {
  669. while( m_index < m_baseSet.size() && ( m_index % 2 != 1 || !m_baseSet.test( m_index ) ) )
  670. {
  671. ++m_index;
  672. }
  673. }
  674. LSET::copper_layers_iterator LSET::copper_layers_begin() const
  675. {
  676. return copper_layers_iterator( *this, 0 );
  677. }
  678. LSET::copper_layers_iterator LSET::copper_layers_end() const
  679. {
  680. return copper_layers_iterator( *this, size() );
  681. }
  682. LSET::non_copper_layers_iterator LSET::non_copper_layers_begin() const
  683. {
  684. return non_copper_layers_iterator( *this, 0 );
  685. }
  686. LSET::non_copper_layers_iterator LSET::non_copper_layers_end() const
  687. {
  688. return non_copper_layers_iterator( *this, size() );
  689. }
  690. #endif