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.

307 lines
10 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-2022 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_PrintEdgeCutsOnAllPages = cfg->m_Plot.edgecut_on_all_layers;
  51. m_Mirror = cfg->m_Plot.mirror;
  52. }
  53. }
  54. void PCBNEW_PRINTOUT_SETTINGS::Save( APP_SETTINGS_BASE* aConfig )
  55. {
  56. BOARD_PRINTOUT_SETTINGS::Save( aConfig );
  57. if( auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aConfig ) )
  58. {
  59. cfg->m_Plot.pads_drill_mode = m_DrillMarks;
  60. cfg->m_Plot.all_layers_on_one_page = m_Pagination;
  61. cfg->m_Plot.edgecut_on_all_layers = m_PrintEdgeCutsOnAllPages;
  62. cfg->m_Plot.mirror = m_Mirror;
  63. }
  64. }
  65. PCBNEW_PRINTOUT::PCBNEW_PRINTOUT( BOARD* aBoard, const PCBNEW_PRINTOUT_SETTINGS& aParams,
  66. const KIGFX::VIEW* aView, const wxString& aTitle ) :
  67. BOARD_PRINTOUT( aParams, aView, aTitle ), m_pcbnewSettings( aParams )
  68. {
  69. m_board = aBoard;
  70. }
  71. bool PCBNEW_PRINTOUT::OnPrintPage( int aPage )
  72. {
  73. // Store the layerset, as it is going to be modified below and the original settings are
  74. // needed.
  75. LSET lset = m_settings.m_LayerSet;
  76. int pageCount = lset.count();
  77. wxString layerName;
  78. PCB_LAYER_ID extractLayer;
  79. // compute layer mask from page number if we want one page per layer
  80. if( m_pcbnewSettings.m_Pagination == PCBNEW_PRINTOUT_SETTINGS::LAYER_PER_PAGE )
  81. {
  82. // This sequence is TBD, call a different sequencer if needed, such as Seq().
  83. // Could not find documentation on page order.
  84. LSEQ seq = lset.UIOrder();
  85. // aPage starts at 1, not 0
  86. if( unsigned( aPage - 1 ) < seq.size() )
  87. m_settings.m_LayerSet = LSET( seq[ aPage - 1] );
  88. }
  89. if( !m_settings.m_LayerSet.any() )
  90. return false;
  91. extractLayer = m_settings.m_LayerSet.ExtractLayer();
  92. if( extractLayer == UNDEFINED_LAYER )
  93. layerName = _( "Multiple Layers" );
  94. else
  95. layerName = m_board->GetLayerName( extractLayer );
  96. // In Pcbnew we can want the layer EDGE always printed
  97. if( m_pcbnewSettings.m_PrintEdgeCutsOnAllPages )
  98. m_settings.m_LayerSet.set( Edge_Cuts );
  99. DrawPage( layerName, aPage, pageCount );
  100. // Restore the original layer set, so the next page can be printed
  101. m_settings.m_LayerSet = lset;
  102. return true;
  103. }
  104. int PCBNEW_PRINTOUT::milsToIU( double aMils ) const
  105. {
  106. return KiROUND( pcbIUScale.IU_PER_MILS * aMils );
  107. }
  108. void PCBNEW_PRINTOUT::setupViewLayers( KIGFX::VIEW& aView, const LSET& aLayerSet )
  109. {
  110. BOARD_PRINTOUT::setupViewLayers( aView, aLayerSet );
  111. for( PCB_LAYER_ID layer : m_settings.m_LayerSet.Seq() )
  112. {
  113. aView.SetLayerVisible( PCBNEW_LAYER_ID_START + layer, true );
  114. // Enable the corresponding zone layer (copper layers and other layers)
  115. aView.SetLayerVisible( LAYER_ZONE_START + layer, true );
  116. }
  117. RENDER_SETTINGS* renderSettings = aView.GetPainter()->GetSettings();
  118. // A color to do not print objects on some layers, when the layer must be enabled
  119. // to print some other objects
  120. COLOR4D invisible_color = COLOR4D::UNSPECIFIED;
  121. if( m_pcbnewSettings.m_AsItemCheckboxes )
  122. {
  123. auto setVisibility =
  124. [&]( GAL_LAYER_ID aLayer )
  125. {
  126. if( m_board->IsElementVisible( aLayer ) )
  127. aView.SetLayerVisible( aLayer, true );
  128. else
  129. renderSettings->SetLayerColor( aLayer, invisible_color );
  130. };
  131. setVisibility( LAYER_MOD_FR );
  132. setVisibility( LAYER_MOD_BK );
  133. setVisibility( LAYER_MOD_VALUES );
  134. setVisibility( LAYER_MOD_REFERENCES );
  135. setVisibility( LAYER_MOD_TEXT );
  136. setVisibility( LAYER_MOD_TEXT_INVISIBLE );
  137. setVisibility( LAYER_PADS );
  138. setVisibility( LAYER_PAD_FR );
  139. setVisibility( LAYER_PAD_BK );
  140. setVisibility( LAYER_PADS_TH );
  141. setVisibility( LAYER_TRACKS );
  142. setVisibility( LAYER_VIAS );
  143. setVisibility( LAYER_VIA_MICROVIA );
  144. setVisibility( LAYER_VIA_BBLIND );
  145. setVisibility( LAYER_VIA_THROUGH );
  146. setVisibility( LAYER_ZONES );
  147. setVisibility( LAYER_DRC_WARNING );
  148. setVisibility( LAYER_DRC_ERROR );
  149. setVisibility( LAYER_DRC_EXCLUSION );
  150. setVisibility( LAYER_ANCHOR );
  151. setVisibility( LAYER_DRAWINGSHEET );
  152. setVisibility( LAYER_GRID );
  153. }
  154. else
  155. {
  156. // Draw layers that must be not visible on printing are set to an invisible layer
  157. // LAYER_PAD_FR, LAYER_PAD_BK and LAYER_PADS_TH must be enabled to print pads on
  158. // technical layers, but not the pad on copper layer(s) if they are not enabled
  159. if( !aLayerSet.test( F_Cu ) )
  160. renderSettings->SetLayerColor( LAYER_PAD_FR, invisible_color );
  161. if( !aLayerSet.test( B_Cu ) )
  162. renderSettings->SetLayerColor( LAYER_PAD_BK, invisible_color );
  163. // Enable items on copper layers, but do not draw holes
  164. for( GAL_LAYER_ID layer : { LAYER_PADS_TH, LAYER_VIA_THROUGH, LAYER_VIA_MICROVIA, LAYER_VIA_BBLIND } )
  165. {
  166. if( ( aLayerSet & LSET::AllCuMask() ).any() ) // Items visible on any copper layer
  167. aView.SetLayerVisible( layer, true );
  168. else
  169. renderSettings->SetLayerColor( layer, invisible_color );
  170. }
  171. // Keep certain items always enabled/disabled and just rely on the layer visibility
  172. // Note LAYER_PAD_FR, LAYER_PAD_BK, LAYER_PADS_TH are enabled here because paths must
  173. // be drawn on some other (technical) layers.
  174. const int alwaysEnabled[] =
  175. {
  176. LAYER_MOD_TEXT, LAYER_MOD_FR, LAYER_MOD_BK,
  177. LAYER_MOD_VALUES, LAYER_MOD_REFERENCES, LAYER_TRACKS, LAYER_ZONES, LAYER_PADS,
  178. LAYER_VIAS,
  179. LAYER_PAD_FR, LAYER_PAD_BK, LAYER_PADS_TH
  180. };
  181. for( int layer : alwaysEnabled )
  182. aView.SetLayerVisible( layer, true );
  183. }
  184. if( m_pcbnewSettings.m_DrillMarks != PCBNEW_PRINTOUT_SETTINGS::NO_DRILL_SHAPE )
  185. {
  186. // Enable hole layers to draw drill marks
  187. for( int layer : { LAYER_PAD_PLATEDHOLES, LAYER_NON_PLATEDHOLES, LAYER_VIA_HOLES } )
  188. {
  189. aView.SetLayerVisible( layer, true );
  190. aView.SetTopLayer( layer, true );
  191. }
  192. }
  193. }
  194. void PCBNEW_PRINTOUT::setupPainter( KIGFX::PAINTER& aPainter )
  195. {
  196. BOARD_PRINTOUT::setupPainter( aPainter );
  197. KIGFX::PCB_PRINT_PAINTER& painter = dynamic_cast<KIGFX::PCB_PRINT_PAINTER&>( aPainter );
  198. switch( m_pcbnewSettings.m_DrillMarks )
  199. {
  200. case PCBNEW_PRINTOUT_SETTINGS::NO_DRILL_SHAPE:
  201. painter.SetDrillMarks( false, 0 );
  202. break;
  203. case PCBNEW_PRINTOUT_SETTINGS::SMALL_DRILL_SHAPE:
  204. painter.SetDrillMarks( false, pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ) );
  205. painter.GetSettings()->SetLayerColor( LAYER_PAD_PLATEDHOLES, COLOR4D::BLACK );
  206. painter.GetSettings()->SetLayerColor( LAYER_NON_PLATEDHOLES, COLOR4D::BLACK );
  207. painter.GetSettings()->SetLayerColor( LAYER_VIA_HOLES, COLOR4D::BLACK );
  208. break;
  209. case PCBNEW_PRINTOUT_SETTINGS::FULL_DRILL_SHAPE:
  210. painter.SetDrillMarks( true );
  211. painter.GetSettings()->SetLayerColor( LAYER_PAD_PLATEDHOLES, COLOR4D::BLACK );
  212. painter.GetSettings()->SetLayerColor( LAYER_NON_PLATEDHOLES, COLOR4D::BLACK );
  213. painter.GetSettings()->SetLayerColor( LAYER_VIA_HOLES, COLOR4D::BLACK );
  214. break;
  215. }
  216. }
  217. void PCBNEW_PRINTOUT::setupGal( KIGFX::GAL* aGal )
  218. {
  219. BOARD_PRINTOUT::setupGal( aGal );
  220. aGal->SetWorldUnitLength( 0.001/pcbIUScale.IU_PER_MM /* 1 nm */ / 0.0254 /* 1 inch in meters */ );
  221. }
  222. BOX2I PCBNEW_PRINTOUT::getBoundingBox()
  223. {
  224. return m_board->ComputeBoundingBox();
  225. }
  226. std::unique_ptr<KIGFX::PAINTER> PCBNEW_PRINTOUT::getPainter( KIGFX::GAL* aGal )
  227. {
  228. return std::make_unique<KIGFX::PCB_PRINT_PAINTER>( aGal );
  229. }
  230. KIGFX::PCB_PRINT_PAINTER::PCB_PRINT_PAINTER( GAL* aGal ) :
  231. PCB_PAINTER( aGal, FRAME_PCB_EDITOR ),
  232. m_drillMarkReal( false ),
  233. m_drillMarkSize( 0 )
  234. { }
  235. int KIGFX::PCB_PRINT_PAINTER::getDrillShape( const PAD* aPad ) const
  236. {
  237. return m_drillMarkReal ? KIGFX::PCB_PAINTER::getDrillShape( aPad ) : PAD_DRILL_SHAPE_CIRCLE;
  238. }
  239. VECTOR2D KIGFX::PCB_PRINT_PAINTER::getDrillSize( const PAD* aPad ) const
  240. {
  241. return m_drillMarkReal ? KIGFX::PCB_PAINTER::getDrillSize( aPad ) :
  242. VECTOR2D( m_drillMarkSize, m_drillMarkSize );
  243. }
  244. int KIGFX::PCB_PRINT_PAINTER::getDrillSize( const PCB_VIA* aVia ) const
  245. {
  246. return m_drillMarkReal ? KIGFX::PCB_PAINTER::getDrillSize( aVia ) : m_drillMarkSize;
  247. }