421 lines
15 KiB
C++
421 lines
15 KiB
C++
|
|
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 1992-2011 KiCad Developers, see change_log.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
|
|
*/
|
|
|
|
#include <wx/wx.h>
|
|
#include "pcb_plot_params.h"
|
|
#include "pcb_plot_params_lexer.h"
|
|
#include "layers_id_colors_and_visibility.h"
|
|
#include "plot_common.h"
|
|
#include "macros.h"
|
|
|
|
|
|
#define PLOT_LINEWIDTH_MIN 0
|
|
#define PLOT_LINEWIDTH_MAX 200
|
|
#define HPGL_PEN_DIAMETER_MIN 0
|
|
#define HPGL_PEN_DIAMETER_MAX 100
|
|
#define HPGL_PEN_SPEED_MIN 0
|
|
#define HPGL_PEN_SPEED_MAX 1000
|
|
#define HPGL_PEN_NUMBER_MIN 1
|
|
#define HPGL_PEN_NUMBER_MAX 16
|
|
#define HPGL_PEN_OVERLAY_MIN 0
|
|
#define HPGL_PEN_OVERLAY_MAX 0x100
|
|
|
|
extern int g_DrawDefaultLineThickness;
|
|
|
|
PCB_PLOT_PARAMS g_PcbPlotOptions;
|
|
|
|
using namespace PCBPLOTPARAMS_T;
|
|
|
|
|
|
static const char* getTokenName( T aTok )
|
|
{
|
|
return PCB_PLOT_PARAMS_LEXER::TokenName( aTok );
|
|
}
|
|
|
|
|
|
static bool setInt( int* aInt, int aValue, int aMin, int aMax )
|
|
{
|
|
int temp = aValue;
|
|
|
|
if( aValue < aMin )
|
|
temp = aMin;
|
|
else if( aValue > aMax )
|
|
temp = aMax;
|
|
|
|
*aInt = temp;
|
|
return (temp == aValue);
|
|
}
|
|
|
|
|
|
// PCB_PLOT_PARAMS
|
|
|
|
PCB_PLOT_PARAMS::PCB_PLOT_PARAMS()
|
|
{
|
|
layerSelection = LAYER_BACK | LAYER_FRONT
|
|
| SILKSCREEN_LAYER_FRONT | SILKSCREEN_LAYER_BACK;
|
|
useGerberExtensions = true;
|
|
m_SkipNPTH_Pads = false;
|
|
m_ExcludeEdgeLayer = true;
|
|
m_PlotLineWidth = g_DrawDefaultLineThickness;
|
|
m_PlotFrameRef = false;
|
|
m_PlotViaOnMaskLayer = false;
|
|
m_PlotMode = FILLED;
|
|
useAuxOrigin = false;
|
|
m_HPGLPenNum = 1;
|
|
m_HPGLPenSpeed = 20;
|
|
m_HPGLPenDiam = 15;
|
|
m_HPGLPenOvr = 2;
|
|
m_PlotPSColorOpt = true;
|
|
m_PlotPSNegative = false;
|
|
psA4Output = false;
|
|
m_PlotReference = true;
|
|
m_PlotValue = true;
|
|
m_PlotTextOther = true;
|
|
m_PlotInvisibleTexts = false;
|
|
m_PlotPadsOnSilkLayer = false;
|
|
subtractMaskFromSilk = false;
|
|
m_PlotFormat = PLOT_FORMAT_GERBER;
|
|
m_PlotMirror = false;
|
|
m_DrillShapeOpt = SMALL_DRILL_SHAPE;
|
|
m_AutoScale = false;
|
|
m_PlotScale = 1.0;
|
|
scaleSelection = 1;
|
|
m_FineScaleAdjustX = 1.0;
|
|
m_FineScaleAdjustY = 1.0;
|
|
m_FineWidthAdjust = 0.;
|
|
outputDirectory = wxT( "" );
|
|
}
|
|
|
|
|
|
void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter,
|
|
int aNestLevel ) const throw( IO_ERROR )
|
|
{
|
|
const char* falseStr = getTokenName( T_false );
|
|
const char* trueStr = getTokenName( T_true );
|
|
|
|
aFormatter->Print( aNestLevel, "(%s", getTokenName( T_pcbplotparams ) );
|
|
aFormatter->Print( aNestLevel+1, "(%s %ld)\n", getTokenName( T_layerselection ),
|
|
layerSelection );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberextensions ),
|
|
useGerberExtensions ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_excludeedgelayer ),
|
|
m_ExcludeEdgeLayer ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_linewidth ),
|
|
m_PlotLineWidth );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_plotframeref ),
|
|
m_PlotFrameRef ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_viasonmask ),
|
|
m_PlotViaOnMaskLayer ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_mode ),
|
|
m_PlotMode );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_useauxorigin ),
|
|
useAuxOrigin ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_hpglpennumber ),
|
|
m_HPGLPenNum );
|
|
aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_hpglpenspeed ),
|
|
m_HPGLPenSpeed );
|
|
aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_hpglpendiameter ),
|
|
m_HPGLPenDiam );
|
|
aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_hpglpenoverlay ),
|
|
m_HPGLPenOvr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_pscolor ),
|
|
m_PlotPSColorOpt ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_psnegative ),
|
|
m_PlotPSNegative ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_psa4output ),
|
|
psA4Output ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_plotreference ),
|
|
m_PlotReference ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_plotvalue ),
|
|
m_PlotValue ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_plotothertext ),
|
|
m_PlotTextOther ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_plotinvisibletext ),
|
|
m_PlotInvisibleTexts ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_padsonsilk ),
|
|
m_PlotPadsOnSilkLayer ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_subtractmaskfromsilk ),
|
|
subtractMaskFromSilk ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_outputformat ),
|
|
m_PlotFormat );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_mirror ),
|
|
m_PlotMirror ? trueStr : falseStr );
|
|
aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_drillshape ),
|
|
m_DrillShapeOpt );
|
|
aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_scaleselection ),
|
|
scaleSelection );
|
|
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_outputdirectory ),
|
|
aFormatter->Quotew( outputDirectory ).c_str() );
|
|
aFormatter->Print( 0, ")\n" );
|
|
}
|
|
|
|
|
|
void PCB_PLOT_PARAMS::Parse( PCB_PLOT_PARAMS_PARSER* aParser ) throw( IO_ERROR, PARSE_ERROR )
|
|
{
|
|
aParser->Parse( this );
|
|
}
|
|
|
|
|
|
bool PCB_PLOT_PARAMS::operator==( const PCB_PLOT_PARAMS &aPcbPlotParams ) const
|
|
{
|
|
if( layerSelection != aPcbPlotParams.layerSelection )
|
|
return false;
|
|
if( useGerberExtensions != aPcbPlotParams.useGerberExtensions )
|
|
return false;
|
|
if( m_ExcludeEdgeLayer != aPcbPlotParams.m_ExcludeEdgeLayer )
|
|
return false;
|
|
if( m_PlotLineWidth != aPcbPlotParams.m_PlotLineWidth )
|
|
return false;
|
|
if( m_PlotFrameRef != aPcbPlotParams.m_PlotFrameRef )
|
|
return false;
|
|
if( m_PlotViaOnMaskLayer != aPcbPlotParams.m_PlotViaOnMaskLayer )
|
|
return false;
|
|
if( m_PlotMode != aPcbPlotParams.m_PlotMode )
|
|
return false;
|
|
if( useAuxOrigin != aPcbPlotParams.useAuxOrigin )
|
|
return false;
|
|
if( m_HPGLPenNum != aPcbPlotParams.m_HPGLPenNum )
|
|
return false;
|
|
if( m_HPGLPenSpeed != aPcbPlotParams.m_HPGLPenSpeed )
|
|
return false;
|
|
if( m_HPGLPenDiam != aPcbPlotParams.m_HPGLPenDiam )
|
|
return false;
|
|
if( m_HPGLPenOvr != aPcbPlotParams.m_HPGLPenOvr )
|
|
return false;
|
|
if( m_PlotPSColorOpt != aPcbPlotParams.m_PlotPSColorOpt )
|
|
return false;
|
|
if( m_PlotPSNegative != aPcbPlotParams.m_PlotPSNegative )
|
|
return false;
|
|
if( psA4Output != aPcbPlotParams.psA4Output )
|
|
return false;
|
|
if( m_PlotReference != aPcbPlotParams.m_PlotReference )
|
|
return false;
|
|
if( m_PlotValue != aPcbPlotParams.m_PlotValue )
|
|
return false;
|
|
if( m_PlotTextOther != aPcbPlotParams.m_PlotTextOther )
|
|
return false;
|
|
if( m_PlotInvisibleTexts != aPcbPlotParams.m_PlotInvisibleTexts )
|
|
return false;
|
|
if( m_PlotPadsOnSilkLayer != aPcbPlotParams.m_PlotPadsOnSilkLayer )
|
|
return false;
|
|
if( subtractMaskFromSilk != aPcbPlotParams.subtractMaskFromSilk )
|
|
return false;
|
|
if( m_PlotFormat != aPcbPlotParams.m_PlotFormat )
|
|
return false;
|
|
if( m_PlotMirror != aPcbPlotParams.m_PlotMirror )
|
|
return false;
|
|
if( m_DrillShapeOpt != aPcbPlotParams.m_DrillShapeOpt )
|
|
return false;
|
|
if( scaleSelection != aPcbPlotParams.scaleSelection )
|
|
return false;
|
|
if( !outputDirectory.IsSameAs( aPcbPlotParams.outputDirectory ) )
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
|
|
bool PCB_PLOT_PARAMS::operator!=( const PCB_PLOT_PARAMS &aPcbPlotParams ) const
|
|
{
|
|
return !( *this == aPcbPlotParams );
|
|
}
|
|
|
|
|
|
bool PCB_PLOT_PARAMS::SetHpglPenDiameter( int aValue )
|
|
{
|
|
return setInt( &m_HPGLPenDiam, aValue, HPGL_PEN_DIAMETER_MIN, HPGL_PEN_DIAMETER_MAX );
|
|
}
|
|
|
|
|
|
bool PCB_PLOT_PARAMS::SetHpglPenSpeed( int aValue )
|
|
{
|
|
return setInt( &m_HPGLPenSpeed, aValue, HPGL_PEN_SPEED_MIN, HPGL_PEN_SPEED_MAX );
|
|
}
|
|
|
|
|
|
bool PCB_PLOT_PARAMS::SetHpglPenOverlay( int aValue )
|
|
{
|
|
return setInt( &m_HPGLPenOvr, aValue, HPGL_PEN_OVERLAY_MIN, HPGL_PEN_OVERLAY_MAX );
|
|
}
|
|
|
|
|
|
bool PCB_PLOT_PARAMS::SetPlotLineWidth( int aValue )
|
|
{
|
|
return setInt( &m_PlotLineWidth, aValue, PLOT_LINEWIDTH_MIN, PLOT_LINEWIDTH_MAX );
|
|
}
|
|
|
|
|
|
// PCB_PLOT_PARAMS_PARSER
|
|
|
|
PCB_PLOT_PARAMS_PARSER::PCB_PLOT_PARAMS_PARSER( LINE_READER* aReader ) :
|
|
PCB_PLOT_PARAMS_LEXER( aReader )
|
|
{
|
|
}
|
|
|
|
|
|
PCB_PLOT_PARAMS_PARSER::PCB_PLOT_PARAMS_PARSER( char* aLine, wxString aSource ) :
|
|
PCB_PLOT_PARAMS_LEXER( aLine, aSource )
|
|
{
|
|
}
|
|
|
|
|
|
void PCB_PLOT_PARAMS_PARSER::Parse( PCB_PLOT_PARAMS* aPcbPlotParams ) throw( IO_ERROR, PARSE_ERROR )
|
|
{
|
|
T token;
|
|
while( ( token = NextTok() ) != T_RIGHT )
|
|
{
|
|
if( token == T_EOF)
|
|
Unexpected( T_EOF );
|
|
|
|
if( token == T_LEFT )
|
|
token = NextTok();
|
|
|
|
if( token == T_pcbplotparams )
|
|
continue;
|
|
|
|
switch( token )
|
|
{
|
|
case T_layerselection:
|
|
token = NextTok();
|
|
if( token != T_NUMBER )
|
|
Expecting( T_NUMBER );
|
|
aPcbPlotParams->layerSelection = atol( CurText() );
|
|
break;
|
|
case T_usegerberextensions:
|
|
aPcbPlotParams->useGerberExtensions = ParseBool();
|
|
break;
|
|
case T_psa4output:
|
|
aPcbPlotParams->psA4Output = ParseBool();
|
|
break;
|
|
case T_excludeedgelayer:
|
|
aPcbPlotParams->m_ExcludeEdgeLayer = ParseBool();
|
|
break;
|
|
case T_linewidth:
|
|
aPcbPlotParams->m_PlotLineWidth = ParseInt( PLOT_LINEWIDTH_MIN,
|
|
PLOT_LINEWIDTH_MAX );
|
|
break;
|
|
case T_plotframeref:
|
|
aPcbPlotParams->m_PlotFrameRef = ParseBool();
|
|
break;
|
|
case T_viasonmask:
|
|
aPcbPlotParams->m_PlotViaOnMaskLayer = ParseBool();
|
|
break;
|
|
case T_mode:
|
|
aPcbPlotParams->m_PlotMode = (EDA_DRAW_MODE_T)ParseInt( 0, 2 );
|
|
break;
|
|
case T_useauxorigin:
|
|
aPcbPlotParams->useAuxOrigin = ParseBool();
|
|
break;
|
|
case T_hpglpennumber:
|
|
aPcbPlotParams->m_HPGLPenNum = ParseInt( HPGL_PEN_NUMBER_MIN,
|
|
HPGL_PEN_NUMBER_MAX );
|
|
break;
|
|
case T_hpglpenspeed:
|
|
aPcbPlotParams->m_HPGLPenSpeed = ParseInt( HPGL_PEN_SPEED_MIN,
|
|
HPGL_PEN_SPEED_MAX );
|
|
break;
|
|
case T_hpglpendiameter:
|
|
aPcbPlotParams->m_HPGLPenDiam = ParseInt( HPGL_PEN_DIAMETER_MIN,
|
|
HPGL_PEN_DIAMETER_MAX );
|
|
break;
|
|
case T_hpglpenoverlay:
|
|
aPcbPlotParams->m_HPGLPenOvr = ParseInt( HPGL_PEN_OVERLAY_MIN,
|
|
HPGL_PEN_OVERLAY_MIN );
|
|
break;
|
|
case T_pscolor:
|
|
aPcbPlotParams->m_PlotPSColorOpt = ParseBool();
|
|
break;
|
|
case T_psnegative:
|
|
aPcbPlotParams->m_PlotPSNegative = ParseBool();
|
|
break;
|
|
case T_plotreference:
|
|
aPcbPlotParams->m_PlotReference = ParseBool();
|
|
break;
|
|
case T_plotvalue:
|
|
aPcbPlotParams->m_PlotValue = ParseBool();
|
|
break;
|
|
case T_plotothertext:
|
|
aPcbPlotParams->m_PlotTextOther = ParseBool();
|
|
break;
|
|
case T_plotinvisibletext:
|
|
aPcbPlotParams->m_PlotInvisibleTexts = ParseBool();
|
|
break;
|
|
case T_padsonsilk:
|
|
aPcbPlotParams->m_PlotPadsOnSilkLayer= ParseBool();
|
|
break;
|
|
case T_subtractmaskfromsilk:
|
|
aPcbPlotParams->subtractMaskFromSilk = ParseBool();
|
|
break;
|
|
case T_outputformat:
|
|
aPcbPlotParams->m_PlotFormat = ParseInt( 0, 3 );
|
|
break;
|
|
case T_mirror:
|
|
aPcbPlotParams->m_PlotMirror = ParseBool();
|
|
break;
|
|
case T_drillshape:
|
|
aPcbPlotParams->m_DrillShapeOpt = (PCB_PLOT_PARAMS::DrillShapeOptT) ParseInt( 0, 2 );
|
|
break;
|
|
case T_scaleselection:
|
|
aPcbPlotParams->scaleSelection = ParseInt( 0, 4 );
|
|
break;
|
|
case T_outputdirectory:
|
|
NeedSYMBOL();
|
|
aPcbPlotParams->outputDirectory = FROM_UTF8( CurText() );
|
|
break;
|
|
default:
|
|
Unexpected( CurText() );
|
|
break;
|
|
}
|
|
NeedRIGHT();
|
|
}
|
|
}
|
|
|
|
|
|
bool PCB_PLOT_PARAMS_PARSER::ParseBool() throw( IO_ERROR )
|
|
{
|
|
T token = NeedSYMBOL();
|
|
|
|
if( token != T_false && token != T_true )
|
|
Expecting( "true|false" );
|
|
|
|
return token == T_true;
|
|
}
|
|
|
|
|
|
int PCB_PLOT_PARAMS_PARSER::ParseInt( int aMin, int aMax ) throw( IO_ERROR )
|
|
{
|
|
T token = NextTok();
|
|
|
|
if( token != T_NUMBER )
|
|
Expecting( T_NUMBER );
|
|
|
|
int val = atoi( CurText() );
|
|
|
|
if( val < aMin )
|
|
val = aMin;
|
|
else if( val > aMax )
|
|
val = aMax;
|
|
|
|
return val;
|
|
}
|