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.

313 lines
11 KiB

5 years ago
5 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2009 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
  5. * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
  6. * Copyright (C) 2018 CERN
  7. * Author: Maciej Suminski <maciej.suminski@cern.ch>
  8. * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, you may find one here:
  22. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  23. * or you may search the http://www.gnu.org website for the version 2 license,
  24. * or you may write to the Free Software Foundation, Inc.,
  25. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  26. */
  27. #include "pcbnew_printout.h"
  28. #include <board.h>
  29. #include <math/util.h> // for KiROUND
  30. #include <pcb_painter.h>
  31. #include <pcbnew_settings.h>
  32. #include <view/view.h>
  33. #include <pcbplot.h>
  34. #include <advanced_config.h>
  35. PCBNEW_PRINTOUT_SETTINGS::PCBNEW_PRINTOUT_SETTINGS( const PAGE_INFO& aPageInfo )
  36. : BOARD_PRINTOUT_SETTINGS( aPageInfo )
  37. {
  38. m_DrillMarks = SMALL_DRILL_SHAPE;
  39. m_Pagination = ALL_LAYERS;
  40. m_PrintEdgeCutsOnAllPages = true;
  41. m_AsItemCheckboxes = false;
  42. }
  43. void PCBNEW_PRINTOUT_SETTINGS::Load( APP_SETTINGS_BASE* aConfig )
  44. {
  45. BOARD_PRINTOUT_SETTINGS::Load( aConfig );
  46. if( auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aConfig ) )
  47. {
  48. m_DrillMarks = static_cast<DRILL_MARK_SHAPE_T>( cfg->m_Plot.pads_drill_mode );
  49. m_Pagination = static_cast<PAGINATION_T>( cfg->m_Plot.all_layers_on_one_page );
  50. m_Mirror = cfg->m_Plot.mirror;
  51. }
  52. }
  53. void PCBNEW_PRINTOUT_SETTINGS::Save( APP_SETTINGS_BASE* aConfig )
  54. {
  55. BOARD_PRINTOUT_SETTINGS::Save( aConfig );
  56. if( auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aConfig ) )
  57. {
  58. cfg->m_Plot.pads_drill_mode = m_DrillMarks;
  59. cfg->m_Plot.all_layers_on_one_page = m_Pagination;
  60. cfg->m_Plot.mirror = m_Mirror;
  61. }
  62. }
  63. PCBNEW_PRINTOUT::PCBNEW_PRINTOUT( BOARD* aBoard, const PCBNEW_PRINTOUT_SETTINGS& aParams,
  64. const KIGFX::VIEW* aView, const wxString& aTitle ) :
  65. BOARD_PRINTOUT( aParams, aView, aTitle ), m_pcbnewSettings( aParams )
  66. {
  67. m_board = aBoard;
  68. }
  69. bool PCBNEW_PRINTOUT::OnPrintPage( int aPage )
  70. {
  71. // Store the layerset, as it is going to be modified below and the original settings are
  72. // needed.
  73. LSET lset = m_settings.m_LayerSet;
  74. int pageCount = lset.count();
  75. wxString layerName;
  76. PCB_LAYER_ID extractLayer;
  77. // compute layer mask from page number if we want one page per layer
  78. if( m_pcbnewSettings.m_Pagination == PCBNEW_PRINTOUT_SETTINGS::LAYER_PER_PAGE )
  79. {
  80. // This sequence is TBD, call a different sequencer if needed, such as Seq().
  81. // Could not find documentation on page order.
  82. LSEQ seq = lset.UIOrder();
  83. // aPage starts at 1, not 0
  84. if( unsigned( aPage - 1 ) < seq.size() )
  85. m_settings.m_LayerSet = LSET( seq[ aPage - 1] );
  86. }
  87. if( !m_settings.m_LayerSet.any() )
  88. return false;
  89. extractLayer = m_settings.m_LayerSet.ExtractLayer();
  90. if( extractLayer == UNDEFINED_LAYER )
  91. layerName = _( "Multiple Layers" );
  92. else
  93. layerName = LSET::Name( extractLayer );
  94. // In Pcbnew we can want the layer EDGE always printed
  95. if( m_pcbnewSettings.m_PrintEdgeCutsOnAllPages )
  96. m_settings.m_LayerSet.set( Edge_Cuts );
  97. DrawPage( layerName, aPage, pageCount );
  98. // Restore the original layer set, so the next page can be printed
  99. m_settings.m_LayerSet = lset;
  100. return true;
  101. }
  102. int PCBNEW_PRINTOUT::milsToIU( double aMils ) const
  103. {
  104. return KiROUND( IU_PER_MILS * aMils );
  105. }
  106. void PCBNEW_PRINTOUT::setupViewLayers( KIGFX::VIEW& aView, const LSET& aLayerSet )
  107. {
  108. BOARD_PRINTOUT::setupViewLayers( aView, aLayerSet );
  109. for( PCB_LAYER_ID layer : m_settings.m_LayerSet.Seq() )
  110. {
  111. aView.SetLayerVisible( PCBNEW_LAYER_ID_START + layer, true );
  112. // Enable the corresponding zone layer (copper layers and other layers)
  113. aView.SetLayerVisible( LAYER_ZONE_START + layer, true );
  114. }
  115. RENDER_SETTINGS* renderSettings = aView.GetPainter()->GetSettings();
  116. // A color to do not print objects on some layers, when the layer must be enabled
  117. // to print some other objects
  118. COLOR4D invisible_color( 0.0, 0.0, 0.0, 0.0 );
  119. if( m_pcbnewSettings.m_AsItemCheckboxes )
  120. {
  121. auto setVisibility =
  122. [&]( GAL_LAYER_ID aLayer )
  123. {
  124. if( m_board->IsElementVisible( aLayer ) )
  125. aView.SetLayerVisible( aLayer, true );
  126. else
  127. renderSettings->SetLayerColor( aLayer, invisible_color );
  128. };
  129. setVisibility( LAYER_MOD_FR );
  130. setVisibility( LAYER_MOD_BK );
  131. setVisibility( LAYER_MOD_VALUES );
  132. setVisibility( LAYER_MOD_REFERENCES );
  133. setVisibility( LAYER_MOD_TEXT );
  134. setVisibility( LAYER_MOD_TEXT_INVISIBLE );
  135. setVisibility( LAYER_PADS );
  136. setVisibility( LAYER_PAD_FR );
  137. setVisibility( LAYER_PAD_BK );
  138. setVisibility( LAYER_PADS_TH );
  139. setVisibility( LAYER_TRACKS );
  140. setVisibility( LAYER_VIAS );
  141. setVisibility( LAYER_VIA_MICROVIA );
  142. setVisibility( LAYER_VIA_BBLIND );
  143. setVisibility( LAYER_VIA_THROUGH );
  144. setVisibility( LAYER_ZONES );
  145. setVisibility( LAYER_NO_CONNECTS );
  146. setVisibility( LAYER_DRC_WARNING );
  147. setVisibility( LAYER_DRC_ERROR );
  148. setVisibility( LAYER_DRC_EXCLUSION );
  149. setVisibility( LAYER_ANCHOR );
  150. setVisibility( LAYER_DRAWINGSHEET );
  151. setVisibility( LAYER_GRID );
  152. }
  153. else
  154. {
  155. // Draw layers that must be not visible on printing are set to an invisible layer
  156. // LAYER_PAD_FR, LAYER_PAD_BK and LAYER_PADS_TH must be enabled to print pads on
  157. // technical layers, but not the pad on copper layer(s) if they are not enabled
  158. if( !aLayerSet.test( F_Cu ) )
  159. renderSettings->SetLayerColor( LAYER_PAD_FR, invisible_color );
  160. if( !aLayerSet.test( B_Cu ) )
  161. renderSettings->SetLayerColor( LAYER_PAD_BK, invisible_color );
  162. // Enable items on copper layers, but do not draw holes
  163. for( GAL_LAYER_ID layer : { LAYER_PADS_TH, LAYER_VIA_THROUGH } )
  164. {
  165. if( ( aLayerSet & LSET::AllCuMask() ).any() ) // Items visible on any copper layer
  166. aView.SetLayerVisible( layer, true );
  167. else
  168. renderSettings->SetLayerColor( layer, invisible_color );
  169. }
  170. // Keep certain items always enabled/disabled and just rely on the layer visibility
  171. // Note LAYER_PAD_FR, LAYER_PAD_BK, LAYER_PADS_TH are enabled here because paths must
  172. // be drawn on some other (technical) layers.
  173. const int alwaysEnabled[] =
  174. {
  175. LAYER_MOD_TEXT, LAYER_MOD_FR, LAYER_MOD_BK,
  176. LAYER_MOD_VALUES, LAYER_MOD_REFERENCES, LAYER_TRACKS, LAYER_ZONES, LAYER_PADS,
  177. LAYER_VIAS, LAYER_VIA_MICROVIA, LAYER_VIA_BBLIND,
  178. LAYER_PAD_FR, LAYER_PAD_BK, LAYER_PADS_TH
  179. };
  180. for( int layer : alwaysEnabled )
  181. aView.SetLayerVisible( layer, true );
  182. }
  183. if( m_pcbnewSettings.m_DrillMarks != PCBNEW_PRINTOUT_SETTINGS::NO_DRILL_SHAPE )
  184. {
  185. // Enable hole layers to draw drill marks
  186. for( int layer : { LAYER_PAD_PLATEDHOLES, LAYER_NON_PLATEDHOLES, LAYER_VIA_HOLES } )
  187. {
  188. aView.SetLayerVisible( layer, true );
  189. aView.SetTopLayer( layer, true );
  190. }
  191. }
  192. }
  193. void PCBNEW_PRINTOUT::setupPainter( KIGFX::PAINTER& aPainter )
  194. {
  195. BOARD_PRINTOUT::setupPainter( aPainter );
  196. KIGFX::PCB_PRINT_PAINTER& painter = dynamic_cast<KIGFX::PCB_PRINT_PAINTER&>( aPainter );
  197. switch( m_pcbnewSettings.m_DrillMarks )
  198. {
  199. case PCBNEW_PRINTOUT_SETTINGS::NO_DRILL_SHAPE:
  200. painter.SetDrillMarks( false, 0 );
  201. break;
  202. case PCBNEW_PRINTOUT_SETTINGS::SMALL_DRILL_SHAPE:
  203. painter.SetDrillMarks( false, Millimeter2iu( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ) );
  204. painter.GetSettings()->SetLayerColor( LAYER_PAD_PLATEDHOLES, COLOR4D::BLACK );
  205. painter.GetSettings()->SetLayerColor( LAYER_NON_PLATEDHOLES, COLOR4D::BLACK );
  206. painter.GetSettings()->SetLayerColor( LAYER_VIA_HOLES, COLOR4D::BLACK );
  207. break;
  208. case PCBNEW_PRINTOUT_SETTINGS::FULL_DRILL_SHAPE:
  209. painter.SetDrillMarks( true );
  210. painter.GetSettings()->SetLayerColor( LAYER_PAD_PLATEDHOLES, COLOR4D::BLACK );
  211. painter.GetSettings()->SetLayerColor( LAYER_NON_PLATEDHOLES, COLOR4D::BLACK );
  212. painter.GetSettings()->SetLayerColor( LAYER_VIA_HOLES, COLOR4D::BLACK );
  213. break;
  214. }
  215. painter.GetSettings()->SetDrawIndividualViaLayers(
  216. m_pcbnewSettings.m_Pagination == PCBNEW_PRINTOUT_SETTINGS::LAYER_PER_PAGE );
  217. }
  218. void PCBNEW_PRINTOUT::setupGal( KIGFX::GAL* aGal )
  219. {
  220. BOARD_PRINTOUT::setupGal( aGal );
  221. aGal->SetWorldUnitLength( 0.001/IU_PER_MM /* 1 nm */ / 0.0254 /* 1 inch in meters */ );
  222. }
  223. EDA_RECT PCBNEW_PRINTOUT::getBoundingBox()
  224. {
  225. return m_board->ComputeBoundingBox();
  226. }
  227. std::unique_ptr<KIGFX::PAINTER> PCBNEW_PRINTOUT::getPainter( KIGFX::GAL* aGal )
  228. {
  229. return std::make_unique<KIGFX::PCB_PRINT_PAINTER>( aGal );
  230. }
  231. KIGFX::PCB_PRINT_PAINTER::PCB_PRINT_PAINTER( GAL* aGal ) :
  232. PCB_PAINTER( aGal ),
  233. m_drillMarkReal( false ),
  234. m_drillMarkSize( 0 )
  235. {
  236. m_pcbSettings.EnableZoneOutlines( false );
  237. }
  238. int KIGFX::PCB_PRINT_PAINTER::getDrillShape( const PAD* aPad ) const
  239. {
  240. return m_drillMarkReal ? KIGFX::PCB_PAINTER::getDrillShape( aPad ) : PAD_DRILL_SHAPE_CIRCLE;
  241. }
  242. VECTOR2D KIGFX::PCB_PRINT_PAINTER::getDrillSize( const PAD* aPad ) const
  243. {
  244. // TODO should it depend on the pad size?
  245. return m_drillMarkReal ? KIGFX::PCB_PAINTER::getDrillSize( aPad ) :
  246. VECTOR2D( m_drillMarkSize, m_drillMarkSize );
  247. }
  248. int KIGFX::PCB_PRINT_PAINTER::getDrillSize( const PCB_VIA* aVia ) const
  249. {
  250. // TODO should it depend on the via size?
  251. return m_drillMarkReal ? KIGFX::PCB_PAINTER::getDrillSize( aVia ) : m_drillMarkSize;
  252. }