mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Recommendation is to avoid using the year nomenclature as this information is already encoded in the git repo. Avoids needing to repeatly update. Also updates AUTHORS.txt from current repo with contributor names
326 lines
11 KiB
C++
326 lines
11 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2009 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
|
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
|
* Copyright (C) 2018 CERN
|
|
* Author: Maciej Suminski <maciej.suminski@cern.ch>
|
|
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, you may find one here:
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include "pcbnew_printout.h"
|
|
#include <board.h>
|
|
#include <math/util.h> // for KiROUND
|
|
#include <gal/graphics_abstraction_layer.h>
|
|
#include <lset.h>
|
|
#include <pcb_painter.h>
|
|
#include <pcbnew_settings.h>
|
|
#include <view/view.h>
|
|
#include <pcbplot.h>
|
|
#include <geometry/shape_segment.h>
|
|
#include <pad.h>
|
|
|
|
#include <advanced_config.h>
|
|
#include <pgm_base.h>
|
|
|
|
PCBNEW_PRINTOUT_SETTINGS::PCBNEW_PRINTOUT_SETTINGS( const PAGE_INFO& aPageInfo ) :
|
|
BOARD_PRINTOUT_SETTINGS( aPageInfo )
|
|
{
|
|
m_DrillMarks = DRILL_MARKS::SMALL_DRILL_SHAPE;
|
|
m_Pagination = ALL_LAYERS;
|
|
m_PrintEdgeCutsOnAllPages = true;
|
|
m_AsItemCheckboxes = false;
|
|
}
|
|
|
|
|
|
void PCBNEW_PRINTOUT_SETTINGS::Load( APP_SETTINGS_BASE* aConfig )
|
|
{
|
|
BOARD_PRINTOUT_SETTINGS::Load( aConfig );
|
|
|
|
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
|
PCBNEW_SETTINGS* cfg = mgr.GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
|
|
|
|
if( cfg )
|
|
{
|
|
m_DrillMarks = static_cast<DRILL_MARKS>( cfg->m_Plot.pads_drill_mode );
|
|
m_Pagination = static_cast<PAGINATION_T>( cfg->m_Plot.all_layers_on_one_page );
|
|
m_PrintEdgeCutsOnAllPages = cfg->m_Plot.edgecut_on_all_layers;
|
|
m_Mirror = cfg->m_Plot.mirror;
|
|
m_AsItemCheckboxes = cfg->m_Plot.as_item_checkboxes;
|
|
}
|
|
}
|
|
|
|
|
|
void PCBNEW_PRINTOUT_SETTINGS::Save( APP_SETTINGS_BASE* aConfig )
|
|
{
|
|
BOARD_PRINTOUT_SETTINGS::Save( aConfig );
|
|
|
|
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
|
PCBNEW_SETTINGS* cfg = mgr.GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
|
|
|
|
if( cfg )
|
|
{
|
|
cfg->m_Plot.pads_drill_mode = (int)m_DrillMarks;
|
|
cfg->m_Plot.all_layers_on_one_page = m_Pagination;
|
|
cfg->m_Plot.edgecut_on_all_layers = m_PrintEdgeCutsOnAllPages;
|
|
cfg->m_Plot.mirror = m_Mirror;
|
|
cfg->m_Plot.as_item_checkboxes = m_AsItemCheckboxes;
|
|
}
|
|
}
|
|
|
|
|
|
PCBNEW_PRINTOUT::PCBNEW_PRINTOUT( BOARD* aBoard, const PCBNEW_PRINTOUT_SETTINGS& aParams,
|
|
const KIGFX::VIEW* aView, const wxString& aTitle ) :
|
|
BOARD_PRINTOUT( aParams, aView, aTitle ), m_pcbnewSettings( aParams )
|
|
{
|
|
m_board = aBoard;
|
|
}
|
|
|
|
|
|
bool PCBNEW_PRINTOUT::OnPrintPage( int aPage )
|
|
{
|
|
// Store the layerset, as it is going to be modified below and the original settings are
|
|
// needed.
|
|
LSET lset = m_settings.m_LayerSet;
|
|
int pageCount = lset.count();
|
|
wxString layerName;
|
|
PCB_LAYER_ID extractLayer;
|
|
|
|
// compute layer mask from page number if we want one page per layer
|
|
if( m_pcbnewSettings.m_Pagination == PCBNEW_PRINTOUT_SETTINGS::LAYER_PER_PAGE )
|
|
{
|
|
// This sequence is TBD, call a different sequencer if needed, such as Seq().
|
|
// Could not find documentation on page order.
|
|
LSEQ seq = lset.UIOrder();
|
|
|
|
// aPage starts at 1, not 0
|
|
if( unsigned( aPage - 1 ) < seq.size() )
|
|
m_settings.m_LayerSet = LSET( { seq[aPage - 1] } );
|
|
}
|
|
|
|
if( !m_settings.m_LayerSet.any() )
|
|
return false;
|
|
|
|
extractLayer = m_settings.m_LayerSet.ExtractLayer();
|
|
|
|
if( extractLayer == UNDEFINED_LAYER )
|
|
layerName = _( "Multiple Layers" );
|
|
else
|
|
layerName = m_board->GetLayerName( extractLayer );
|
|
|
|
// In Pcbnew we can want the layer EDGE always printed
|
|
if( m_pcbnewSettings.m_PrintEdgeCutsOnAllPages )
|
|
m_settings.m_LayerSet.set( Edge_Cuts );
|
|
|
|
DrawPage( layerName, aPage, pageCount );
|
|
|
|
// Restore the original layer set, so the next page can be printed
|
|
m_settings.m_LayerSet = lset;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
int PCBNEW_PRINTOUT::milsToIU( double aMils ) const
|
|
{
|
|
return KiROUND( pcbIUScale.IU_PER_MILS * aMils );
|
|
}
|
|
|
|
|
|
void PCBNEW_PRINTOUT::setupViewLayers( KIGFX::VIEW& aView, const LSET& aLayerSet )
|
|
{
|
|
BOARD_PRINTOUT::setupViewLayers( aView, aLayerSet );
|
|
|
|
for( PCB_LAYER_ID layer : m_settings.m_LayerSet.Seq() )
|
|
{
|
|
aView.SetLayerVisible( PCBNEW_LAYER_ID_START + layer, true );
|
|
|
|
// Enable the corresponding zone layer (copper layers and other layers)
|
|
aView.SetLayerVisible( LAYER_ZONE_START + layer, true );
|
|
aView.SetLayerVisible( LAYER_PAD_COPPER_START + layer, true );
|
|
aView.SetLayerVisible( LAYER_VIA_COPPER_START + layer, true );
|
|
}
|
|
|
|
RENDER_SETTINGS* renderSettings = aView.GetPainter()->GetSettings();
|
|
// A color to do not print objects on some layers, when the layer must be enabled
|
|
// to print some other objects
|
|
COLOR4D invisible_color = COLOR4D::UNSPECIFIED;
|
|
|
|
if( m_pcbnewSettings.m_AsItemCheckboxes )
|
|
{
|
|
auto setVisibility =
|
|
[&]( GAL_LAYER_ID aLayer )
|
|
{
|
|
if( m_board->IsElementVisible( aLayer ) )
|
|
aView.SetLayerVisible( aLayer, true );
|
|
else
|
|
renderSettings->SetLayerColor( aLayer, invisible_color );
|
|
};
|
|
|
|
setVisibility( LAYER_FOOTPRINTS_FR );
|
|
setVisibility( LAYER_FOOTPRINTS_BK );
|
|
setVisibility( LAYER_FP_VALUES );
|
|
setVisibility( LAYER_FP_REFERENCES );
|
|
setVisibility( LAYER_FP_TEXT );
|
|
setVisibility( LAYER_PADS );
|
|
|
|
setVisibility( LAYER_TRACKS );
|
|
setVisibility( LAYER_VIAS );
|
|
setVisibility( LAYER_VIA_MICROVIA );
|
|
setVisibility( LAYER_VIA_BBLIND );
|
|
setVisibility( LAYER_VIA_THROUGH );
|
|
setVisibility( LAYER_ZONES );
|
|
setVisibility( LAYER_SHAPES );
|
|
|
|
setVisibility( LAYER_DRC_WARNING );
|
|
setVisibility( LAYER_DRC_ERROR );
|
|
setVisibility( LAYER_DRC_SHAPE1 );
|
|
setVisibility( LAYER_DRC_SHAPE2 );
|
|
setVisibility( LAYER_DRC_EXCLUSION );
|
|
setVisibility( LAYER_ANCHOR );
|
|
setVisibility( LAYER_DRAWINGSHEET );
|
|
setVisibility( LAYER_GRID );
|
|
}
|
|
else
|
|
{
|
|
// Enable items on copper layers, but do not draw holes
|
|
for( GAL_LAYER_ID layer : { LAYER_VIA_THROUGH, LAYER_VIA_MICROVIA, LAYER_VIA_BBLIND } )
|
|
{
|
|
if( ( aLayerSet & LSET::AllCuMask() ).any() ) // Items visible on any copper layer
|
|
aView.SetLayerVisible( layer, true );
|
|
else
|
|
renderSettings->SetLayerColor( layer, invisible_color );
|
|
}
|
|
|
|
// Keep certain items always enabled/disabled and just rely on the layer visibility
|
|
// Note LAYER_PADS_SMD_FR, LAYER_PADS_SMD_BK, LAYER_PADS_TH are enabled here because paths must
|
|
// be drawn on some other (technical) layers.
|
|
const int alwaysEnabled[] =
|
|
{
|
|
LAYER_FP_TEXT, LAYER_FP_VALUES, LAYER_FP_REFERENCES,
|
|
LAYER_FOOTPRINTS_FR, LAYER_FOOTPRINTS_BK,
|
|
LAYER_TRACKS, LAYER_VIAS,
|
|
LAYER_ZONES, LAYER_SHAPES,
|
|
LAYER_PADS
|
|
};
|
|
|
|
for( int layer : alwaysEnabled )
|
|
aView.SetLayerVisible( layer, true );
|
|
}
|
|
|
|
if( m_pcbnewSettings.m_DrillMarks != DRILL_MARKS::NO_DRILL_SHAPE )
|
|
{
|
|
// Enable hole layers to draw drill marks
|
|
for( int layer : { LAYER_PAD_PLATEDHOLES, LAYER_NON_PLATEDHOLES, LAYER_VIA_HOLES } )
|
|
{
|
|
aView.SetLayerVisible( layer, true );
|
|
aView.SetTopLayer( layer, true );
|
|
}
|
|
|
|
if( m_pcbnewSettings.m_DrillMarks == DRILL_MARKS::FULL_DRILL_SHAPE
|
|
&& !m_settings.m_blackWhite )
|
|
{
|
|
for( int layer : { LAYER_PAD_HOLEWALLS, LAYER_VIA_HOLEWALLS } )
|
|
{
|
|
aView.SetLayerVisible( layer, true );
|
|
aView.SetTopLayer( layer, true );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void PCBNEW_PRINTOUT::setupPainter( KIGFX::PAINTER& aPainter )
|
|
{
|
|
BOARD_PRINTOUT::setupPainter( aPainter );
|
|
|
|
KIGFX::PCB_PRINT_PAINTER& painter = dynamic_cast<KIGFX::PCB_PRINT_PAINTER&>( aPainter );
|
|
|
|
switch( m_pcbnewSettings.m_DrillMarks )
|
|
{
|
|
case DRILL_MARKS::NO_DRILL_SHAPE:
|
|
painter.SetDrillMarks( false, 0 );
|
|
break;
|
|
|
|
case DRILL_MARKS::SMALL_DRILL_SHAPE:
|
|
painter.SetDrillMarks( false, pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ) );
|
|
|
|
painter.GetSettings()->SetLayerColor( LAYER_PAD_PLATEDHOLES, COLOR4D::BLACK );
|
|
painter.GetSettings()->SetLayerColor( LAYER_NON_PLATEDHOLES, COLOR4D::BLACK );
|
|
painter.GetSettings()->SetLayerColor( LAYER_VIA_HOLES, COLOR4D::BLACK );
|
|
break;
|
|
|
|
case DRILL_MARKS::FULL_DRILL_SHAPE:
|
|
painter.SetDrillMarks( true );
|
|
|
|
painter.GetSettings()->SetLayerColor( LAYER_PAD_PLATEDHOLES, COLOR4D::BLACK );
|
|
painter.GetSettings()->SetLayerColor( LAYER_NON_PLATEDHOLES, COLOR4D::BLACK );
|
|
painter.GetSettings()->SetLayerColor( LAYER_VIA_HOLES, COLOR4D::BLACK );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void PCBNEW_PRINTOUT::setupGal( KIGFX::GAL* aGal )
|
|
{
|
|
BOARD_PRINTOUT::setupGal( aGal );
|
|
aGal->SetWorldUnitLength( 0.001/pcbIUScale.IU_PER_MM /* 1 nm */ / 0.0254 /* 1 inch in meters */ );
|
|
}
|
|
|
|
|
|
BOX2I PCBNEW_PRINTOUT::getBoundingBox()
|
|
{
|
|
return m_board->ComputeBoundingBox( false );
|
|
}
|
|
|
|
|
|
std::unique_ptr<KIGFX::PAINTER> PCBNEW_PRINTOUT::getPainter( KIGFX::GAL* aGal )
|
|
{
|
|
return std::make_unique<KIGFX::PCB_PRINT_PAINTER>( aGal );
|
|
}
|
|
|
|
|
|
KIGFX::PCB_PRINT_PAINTER::PCB_PRINT_PAINTER( GAL* aGal ) :
|
|
PCB_PAINTER( aGal, FRAME_PCB_EDITOR ),
|
|
m_drillMarkReal( false ),
|
|
m_drillMarkSize( 0 )
|
|
{ }
|
|
|
|
|
|
PAD_DRILL_SHAPE KIGFX::PCB_PRINT_PAINTER::getDrillShape( const PAD* aPad ) const
|
|
{
|
|
return m_drillMarkReal ? KIGFX::PCB_PAINTER::getDrillShape( aPad ) : PAD_DRILL_SHAPE::CIRCLE;
|
|
}
|
|
|
|
|
|
SHAPE_SEGMENT KIGFX::PCB_PRINT_PAINTER::getPadHoleShape( const PAD* aPad ) const
|
|
{
|
|
if( m_drillMarkReal )
|
|
return KIGFX::PCB_PAINTER::getPadHoleShape( aPad );
|
|
else
|
|
return SHAPE_SEGMENT( aPad->GetPosition(), aPad->GetPosition(), m_drillMarkSize );
|
|
}
|
|
|
|
|
|
int KIGFX::PCB_PRINT_PAINTER::getViaDrillSize( const PCB_VIA* aVia ) const
|
|
{
|
|
return m_drillMarkReal ? KIGFX::PCB_PAINTER::getViaDrillSize( aVia ) : m_drillMarkSize;
|
|
}
|