/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. * * 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 */ /** * @file pcbnew/pcbplot.cpp */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include wxString GetGerberExtension( LAYER_NUM layer ) { switch( layer ) { case LAYER_N_FRONT: return wxString( wxT( "gtl" ) ); case LAYER_N_2: case LAYER_N_3: case LAYER_N_4: case LAYER_N_5: case LAYER_N_6: case LAYER_N_7: case LAYER_N_8: case LAYER_N_9: case LAYER_N_10: case LAYER_N_11: case LAYER_N_12: case LAYER_N_13: case LAYER_N_14: case LAYER_N_15: // TODO: see if we use .gbr or a layer identifier (gb1 .. gbnn ?) // according to the new internal layers designation // (1 is the first internal layer from the front layer) return wxString( wxT( "gbr" ) ); case LAYER_N_BACK: return wxString( wxT( "gbl" ) ); case ADHESIVE_N_BACK: return wxString( wxT( "gba" ) ); case ADHESIVE_N_FRONT: return wxString( wxT( "gta" ) ); case SOLDERPASTE_N_BACK: return wxString( wxT( "gbp" ) ); case SOLDERPASTE_N_FRONT: return wxString( wxT( "gtp" ) ); case SILKSCREEN_N_BACK: return wxString( wxT( "gbo" ) ); case SILKSCREEN_N_FRONT: return wxString( wxT( "gto" ) ); case SOLDERMASK_N_BACK: return wxString( wxT( "gbs" ) ); case SOLDERMASK_N_FRONT: return wxString( wxT( "gts" ) ); case DRAW_N: case COMMENT_N: case ECO1_N: case ECO2_N: case EDGE_N: default: return wxString( wxT( "gbr" ) ); } } void BuildPlotFileName( wxFileName* aFilename, const wxString& aOutputDir, const wxString& aSuffix, const wxString& aExtension ) { aFilename->SetPath( aOutputDir ); // Set the file extension aFilename->SetExt( aExtension ); /* remove leading and trailing spaces if any from the suffix, if something survives add it to the name; also the suffix can contain some not allowed chars in filename (/ \ .), so change them to underscore */ wxString suffix = aSuffix; suffix.Trim( true ); suffix.Trim( false ); suffix.Replace( wxT("."), wxT("_") ); suffix.Replace( wxT("/"), wxT("_") ); suffix.Replace( wxT("\\"), wxT("_") ); if( !suffix.IsEmpty() ) aFilename->SetName( aFilename->GetName() + wxT( "-" ) + suffix ); } bool EnsureOutputDirectory( wxFileName* aOutputDir, const wxString& aBoardFilename, REPORTER* aReporter ) { wxString msg; wxString boardFilePath = wxFileName( aBoardFilename ).GetPath(); if( !aOutputDir->MakeAbsolute( boardFilePath ) ) { if( aReporter ) { msg.Printf( _( "*** Error: cannot make path '%s' absolute with respect to '%s'! ***" ), GetChars( aOutputDir->GetPath() ), GetChars( boardFilePath ) ); aReporter->Report( msg ); } return false; } wxString outputPath( aOutputDir->GetPath() ); if( !wxFileName::DirExists( outputPath ) ) { if( wxMkdir( outputPath ) ) { if( aReporter ) { msg.Printf( _( "Output directory '%s' created.\n" ), GetChars( outputPath ) ); aReporter->Report( msg ); return true; } } else { if( aReporter ) { msg.Printf( _( "*** Error: cannot create output directory '%s'! ***\n" ), GetChars( outputPath ) ); aReporter->Report( msg ); } return false; } } return true; } PLOT_CONTROLLER::PLOT_CONTROLLER( BOARD *aBoard ) : m_plotter( NULL ), m_board( aBoard ) { } PLOT_CONTROLLER::~PLOT_CONTROLLER() { ClosePlot(); } /* IMPORTANT THING TO KNOW: the locale during plots *MUST* be kept as * C/POSIX using a LOCALE_IO object on the stack. This even when * opening/closing the plotfile, since some drivers do I/O even then */ void PLOT_CONTROLLER::ClosePlot() { LOCALE_IO toggle; if( m_plotter ) { m_plotter->EndPlot(); delete m_plotter; m_plotter = NULL; } } bool PLOT_CONTROLLER::OpenPlotfile( const wxString &aSuffix, PlotFormat aFormat, const wxString &aSheetDesc ) { LOCALE_IO toggle; /* Save the current format: sadly some plot routines depends on this but the main reason is that the StartPlot method uses it to dispatch the plotter creation */ m_plotOpts.SetFormat( aFormat ); // Ensure that the previous plot is closed ClosePlot(); // Now compute the full filename for the output and start the plot // (after ensuring the output directory is OK) wxString outputDirName = m_plotOpts.GetOutputDirectory() ; wxFileName outputDir = wxFileName::DirName( outputDirName ); wxString boardFilename = m_board->GetFileName(); if( EnsureOutputDirectory( &outputDir, boardFilename ) ) { wxFileName fn( boardFilename ); BuildPlotFileName( &fn, outputDirName, aSuffix, GetDefaultPlotExtension( aFormat ) ); m_plotter = StartPlotBoard( m_board, &m_plotOpts, fn.GetFullPath(), aSheetDesc ); } return( m_plotter != NULL ); } bool PLOT_CONTROLLER::PlotLayer( LAYER_NUM aLayer ) { LOCALE_IO toggle; // No plot open, nothing to do... if( !m_plotter ) return false; // Fully delegated to the parent PlotOneBoardLayer( m_board, m_plotter, aLayer, m_plotOpts ); return true; } void PLOT_CONTROLLER::SetColorMode( bool aColorMode ) { if( !m_plotter ) return; m_plotter->SetColorMode( aColorMode ); } bool PLOT_CONTROLLER::GetColorMode() { if( !m_plotter ) return false; return m_plotter->GetColorMode(); }