Commit 2caa72f0 authored by Александр Закамалдин's avatar Александр Закамалдин Committed by Dick Hollenbeck

This patch implements width tuning (width correction) for PS plotting of tracks, pads and vias.

This feature is very useful for electronics hobbyists who use DIY PCB technology 
(both toner transfer and photoresist methods).
Also width correction may be useful for PCB designers who take care of track width etching.
This patch also fixes some minor PS plotting issues.
parent c3c6b9ef
......@@ -491,16 +491,18 @@ void PS_PLOTTER::flash_pad_oval( wxPoint pos, wxSize size, int orient,
void PS_PLOTTER::flash_pad_circle( wxPoint pos, int diametre,
EDA_DRAW_MODE_T modetrace )
{
int current_line_width;
wxASSERT( output_file );
set_current_line_width( -1 );
if( current_pen_width >= diametre )
set_current_line_width( diametre );
current_line_width = get_current_line_width();
if( current_line_width > diametre )
current_line_width = diametre;
if( modetrace == FILLED )
circle( pos, diametre - current_pen_width, FILLED_SHAPE );
circle( pos, diametre - current_pen_width, FILLED_SHAPE, current_line_width );
else
circle( pos, diametre - current_pen_width, NO_FILL );
circle( pos, diametre - current_pen_width, NO_FILL, current_line_width );
set_current_line_width( -1 );
}
......
......@@ -71,6 +71,20 @@ public:
virtual void set_color( int color ) = 0;
virtual void set_dash( bool dashed ) = 0;
virtual int get_current_line_width()
{
return current_pen_width;
}
virtual void set_plot_width_adj( double width )
{
}
virtual double get_plot_width_adj()
{
return 0.;
}
virtual void set_creator( const wxString& _creator )
{
creator = _creator;
......@@ -390,6 +404,7 @@ public:
protected:
double plot_scale_adjX, plot_scale_adjY;
double plot_width_adj;
};
/* Class to handle a D_CODE when plotting a board : */
......
......@@ -286,6 +286,21 @@ int BOARD::GetBiggestClearanceValue()
}
int BOARD::GetSmallestClearanceValue()
{
int clearance = m_NetClasses.GetDefault()->GetClearance();
//Read list of Net Classes
for( NETCLASSES::const_iterator nc = m_NetClasses.begin(); nc != m_NetClasses.end(); nc++ )
{
NETCLASS* netclass = nc->second;
clearance = MIN( clearance, netclass->GetClearance() );
}
return clearance;
}
int BOARD::GetCurrentMicroViaSize()
{
NETCLASS* netclass = m_NetClasses.Find( m_CurrentNetClassName );
......
......@@ -816,6 +816,12 @@ public:
*/
int GetBiggestClearanceValue();
/**
* Function GetSmallestClearanceValue
* @return the smallest clearance value found in NetClasses list
*/
int GetSmallestClearanceValue();
/**
* Function GetCurrentTrackWidth
* @return the current track width, according to the selected options
......
......@@ -179,7 +179,6 @@ DIALOG_PLOT_BASE::DIALOG_PLOT_BASE( wxWindow* parent, wxWindowID id, const wxStr
m_GerberOptionsSizer->Add( m_excludeEdgeLayerOpt, 0, wxTOP|wxRIGHT|wxLEFT, 2 );
m_subtractMaskFromSilk = new wxCheckBox( this, wxID_ANY, _("Subtract soldermask from silkscreen"), wxDefaultPosition, wxDefaultSize, 0 );
m_subtractMaskFromSilk->SetValue(true);
m_subtractMaskFromSilk->SetToolTip( _("Remove silkscreen from areas without soldermask") );
m_GerberOptionsSizer->Add( m_subtractMaskFromSilk, 0, wxTOP|wxRIGHT|wxLEFT, 2 );
......@@ -268,6 +267,20 @@ DIALOG_PLOT_BASE::DIALOG_PLOT_BASE( wxWindow* parent, wxWindowID id, const wxStr
bSizer17->Add( bSizer19, 1, wxEXPAND, 5 );
wxBoxSizer* bSizer191;
bSizer191 = new wxBoxSizer( wxVERTICAL );
m_textPSFineAdjustWidth = new wxStaticText( this, wxID_ANY, _("Width correction"), wxDefaultPosition, wxDefaultSize, 0 );
m_textPSFineAdjustWidth->Wrap( -1 );
bSizer191->Add( m_textPSFineAdjustWidth, 0, wxLEFT|wxRIGHT|wxTOP, 5 );
m_PSFineAdjustWidthOpt = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_PSFineAdjustWidthOpt->SetToolTip( _("Set global width correction for exact width postscript output.\nThese width correction is intended to compensate tracks width and also pads and vias size errors.\nThe reasonable width correction value must be in a range of [-(MinTrackWidth-1), +(MinClearanceValue-1)] in decimils.") );
bSizer191->Add( m_PSFineAdjustWidthOpt, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 );
bSizer17->Add( bSizer191, 1, wxEXPAND, 5 );
m_PSOptionsSizer->Add( bSizer17, 1, wxEXPAND, 5 );
m_plotPSNegativeOpt = new wxCheckBox( this, wxID_ANY, _("Negative plot"), wxDefaultPosition, wxDefaultSize, 0 );
......
This diff is collapsed.
......@@ -85,6 +85,8 @@ class DIALOG_PLOT_BASE : public wxDialog
wxTextCtrl* m_fineAdjustXscaleOpt;
wxStaticText* m_staticText8;
wxTextCtrl* m_fineAdjustYscaleOpt;
wxStaticText* m_textPSFineAdjustWidth;
wxTextCtrl* m_PSFineAdjustWidthOpt;
wxCheckBox* m_plotPSNegativeOpt;
wxCheckBox* m_forcePSA4OutputOpt;
wxTextCtrl* m_messagesBox;
......
......@@ -102,6 +102,7 @@ PCB_PLOT_PARAMS::PCB_PLOT_PARAMS()
scaleSelection = 1;
m_FineScaleAdjustX = 1.0;
m_FineScaleAdjustY = 1.0;
m_FineWidthAdjust = 0.;
outputDirectory = wxT( "" );
}
......
......@@ -86,6 +86,8 @@ public:
// Only X and Y dimensions are adjusted: circles are plotted as circle, even if X and Y fine scale differ.
double m_FineScaleAdjustX; // fine scale adjust X axis
double m_FineScaleAdjustY; // dine scale adjust Y axis
// These width factor is intended to compensate plotters (and mainly printers) line width error.
double m_FineWidthAdjust;
private:
long layerSelection;
......
......@@ -24,6 +24,7 @@
/* Keywords to r/w options in m_Config */
#define CONFIG_XFINESCALE_ADJ wxT( "PlotXFineScaleAdj" )
#define CONFIG_YFINESCALE_ADJ wxT( "PlotYFineScaleAdj" )
#define CONFIG_PS_FINEWIDTH_ADJ wxT( "PSPlotFineWidthAdj" )
// Define min and max reasonable values for print scale
#define MIN_SCALE 0.01
......@@ -62,6 +63,9 @@ private:
std::vector<int> layerList; // List to hold CheckListBox layer numbers
double m_XScaleAdjust;
double m_YScaleAdjust;
double m_PSWidthAdjust; // Global width correction for exact width postscript output.
double m_WidthAdjustMinValue; // Global width correction
double m_WidthAdjustMaxValue; // margins.
static wxPoint prevPosition; // Dialog position & size
static wxSize prevSize;
......@@ -114,6 +118,12 @@ void DIALOG_PLOT::Init_Dialog()
m_Config->Read( CONFIG_XFINESCALE_ADJ, &m_XScaleAdjust );
m_Config->Read( CONFIG_YFINESCALE_ADJ, &m_YScaleAdjust );
m_Config->Read( CONFIG_PS_FINEWIDTH_ADJ, &m_PSWidthAdjust);
// The reasonable width correction value must be in a range of
// [-(MinTrackWidth-1), +(MinClearanceValue-1)] decimils.
m_WidthAdjustMinValue = -(board->GetDesignSettings().m_TrackMinWidth - 1);
m_WidthAdjustMaxValue = board->GetSmallestClearanceValue() - 1;
m_plotFormatOpt->SetSelection( g_PcbPlotOptions.GetPlotFormat() );
......@@ -136,6 +146,9 @@ void DIALOG_PLOT::Init_Dialog()
PCB_INTERNAL_UNIT );
m_linesWidth->AppendText( msg );
// Set units for PS global width correction.
AddUnitSymbol( *m_textPSFineAdjustWidth, g_UserUnit );
m_useAuxOriginCheckBox->SetValue( g_PcbPlotOptions.GetUseAuxOrigin() );
// Test for a reasonable scale value. Set to 1 if problem
......@@ -149,6 +162,13 @@ void DIALOG_PLOT::Init_Dialog()
msg.Printf( wxT( "%f" ), m_YScaleAdjust );
m_fineAdjustYscaleOpt->AppendText( msg );
// Test for a reasonable PS width correction value. Set to 0 if problem.
if( m_PSWidthAdjust < m_WidthAdjustMinValue || m_PSWidthAdjust > m_WidthAdjustMaxValue )
m_PSWidthAdjust = 0.;
msg.Printf( wxT( "%f" ), To_User_Unit( g_UserUnit, m_PSWidthAdjust, PCB_INTERNAL_UNIT ) );
m_PSFineAdjustWidthOpt->AppendText( msg );
m_plotPSNegativeOpt->SetValue( g_PcbPlotOptions.m_PlotPSNegative );
m_forcePSA4OutputOpt->SetValue( g_PcbPlotOptions.GetPsA4Output() );
......@@ -319,6 +339,7 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
m_scaleOpt->Enable( true );
m_fineAdjustXscaleOpt->Enable( true );
m_fineAdjustYscaleOpt->Enable( true );
m_PSFineAdjustWidthOpt->Enable( true );
m_plotPSNegativeOpt->Enable( true );
m_PlotOptionsSizer->Hide( m_GerberOptionsSizer );
m_PlotOptionsSizer->Hide( m_HPGLOptionsSizer );
......@@ -345,6 +366,7 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
m_scaleOpt->Enable( false );
m_fineAdjustXscaleOpt->Enable( false );
m_fineAdjustYscaleOpt->Enable( false );
m_PSFineAdjustWidthOpt->Enable( false );
m_plotPSNegativeOpt->SetValue( false );
m_plotPSNegativeOpt->Enable( false );
m_PlotOptionsSizer->Show( m_GerberOptionsSizer );
......@@ -370,6 +392,7 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
m_scaleOpt->Enable( true );
m_fineAdjustXscaleOpt->Enable( false );
m_fineAdjustYscaleOpt->Enable( false );
m_PSFineAdjustWidthOpt->Enable( false );
m_plotPSNegativeOpt->SetValue( false );
m_plotPSNegativeOpt->Enable( false );
m_PlotOptionsSizer->Hide( m_GerberOptionsSizer );
......@@ -397,6 +420,7 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
m_scaleOpt->SetSelection( 1 );
m_fineAdjustXscaleOpt->Enable( false );
m_fineAdjustYscaleOpt->Enable( false );
m_PSFineAdjustWidthOpt->Enable( false );
m_plotPSNegativeOpt->SetValue( false );
m_plotPSNegativeOpt->Enable( false );
m_PlotOptionsSizer->Hide( m_GerberOptionsSizer );
......@@ -517,6 +541,25 @@ void DIALOG_PLOT::applyPlotSettings()
m_Config->Write( CONFIG_YFINESCALE_ADJ, m_YScaleAdjust );
// PS Width correction
msg = m_PSFineAdjustWidthOpt->GetValue();
tmpDouble = ReturnValueFromString( g_UserUnit, msg, PCB_INTERNAL_UNIT );
if( !setDouble( &m_PSWidthAdjust, tmpDouble, m_WidthAdjustMinValue, m_WidthAdjustMaxValue ) )
{
msg = ReturnStringFromValue( g_UserUnit, m_PSWidthAdjust, PCB_INTERNAL_UNIT );
m_PSFineAdjustWidthOpt->SetValue( msg );
msg.Printf( wxT( "Width correction constrained!\n"
"The reasonable width correction value must be in a range of [%+f; %+f]" ),
To_User_Unit( g_UserUnit, m_WidthAdjustMinValue, PCB_INTERNAL_UNIT ),
To_User_Unit( g_UserUnit, m_WidthAdjustMaxValue, PCB_INTERNAL_UNIT ) );
msg += ( g_UserUnit == INCHES )? _(" (\")") : _(" (mm)");
msg += wxT( " for current design rules!\n" );
m_messagesBox->AppendText( msg );
}
m_Config->Write( CONFIG_PS_FINEWIDTH_ADJ, m_PSWidthAdjust );
tempOptions.SetUseGerberExtensions( m_useGerberExtensions->GetValue() );
tempOptions.SetPlotFormat( m_plotFormatOpt->GetSelection() );
......@@ -624,6 +667,9 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event )
if( m_fineAdjustYscaleOpt->IsEnabled() && m_YScaleAdjust != 0.0 )
g_PcbPlotOptions.m_FineScaleAdjustY = m_YScaleAdjust;
if( m_PSFineAdjustWidthOpt->IsEnabled() )
g_PcbPlotOptions.m_FineWidthAdjust = m_PSWidthAdjust;
switch( g_PcbPlotOptions.GetPlotFormat() )
{
case PLOT_FORMAT_POST:
......
......@@ -32,6 +32,12 @@ static void Plot_Edges_Modules( PLOTTER* plotter, BOARD* pcb, int aLayerMask,
static void PlotTextModule( PLOTTER* plotter, TEXTE_MODULE* pt_texte,
EDA_DRAW_MODE_T trace_mode );
static int doIntValueFitToBand( int aInt, int aMin, int aMax )
{
if( aInt < aMin ) return aMin;
if( aInt > aMax ) return aMax;
return aInt;
}
/* Creates the plot for silkscreen layers
*/
......@@ -808,6 +814,12 @@ void PCB_BASE_FRAME::Plot_Standard_Layer( PLOTTER* aPlotter,
shape_pos = pad->ReturnShapePos();
pos = shape_pos;
wxSize margin;
double width_adj = 0;
if( aLayerMask & ALL_CU_LAYERS )
{
width_adj = aPlotter->get_plot_width_adj();
}
switch( aLayerMask &
( SOLDERMASK_LAYER_BACK | SOLDERMASK_LAYER_FRONT |
......@@ -827,8 +839,8 @@ void PCB_BASE_FRAME::Plot_Standard_Layer( PLOTTER* aPlotter,
break;
}
size.x = pad->m_Size.x + ( 2 * margin.x );
size.y = pad->m_Size.y + ( 2 * margin.y );
size.x = pad->m_Size.x + ( 2 * margin.x ) + width_adj;
size.y = pad->m_Size.y + ( 2 * margin.y ) + width_adj;
/* Don't draw a null size item : */
if( size.x <= 0 || size.y <= 0 )
......@@ -895,14 +907,20 @@ void PCB_BASE_FRAME::Plot_Standard_Layer( PLOTTER* aPlotter,
continue;
int via_margin = 0;
double width_adj = 0;
// If the current layer is a solder mask, use the global mask
// clearance for vias
if( ( aLayerMask & ( SOLDERMASK_LAYER_BACK | SOLDERMASK_LAYER_FRONT ) ) )
via_margin = GetBoard()->GetDesignSettings().m_SolderMaskMargin;
if( aLayerMask & ALL_CU_LAYERS )
{
width_adj = aPlotter->get_plot_width_adj();
}
pos = Via->m_Start;
size.x = size.y = Via->m_Width + 2 * via_margin;
size.x = size.y = Via->m_Width + 2 * via_margin + width_adj;
/* Don't draw a null size item : */
if( size.x <= 0 )
......@@ -923,7 +941,7 @@ void PCB_BASE_FRAME::Plot_Standard_Layer( PLOTTER* aPlotter,
if( (GetLayerMask( track->GetLayer() ) & aLayerMask) == 0 )
continue;
size.x = size.y = track->m_Width;
size.x = size.y = track->m_Width + aPlotter->get_plot_width_adj();
pos = track->m_Start;
end = track->m_End;
......@@ -938,7 +956,7 @@ void PCB_BASE_FRAME::Plot_Standard_Layer( PLOTTER* aPlotter,
if( (GetLayerMask( track->GetLayer() ) & aLayerMask) == 0 )
continue;
size.x = size.y = track->m_Width;
size.x = size.y = track->m_Width + aPlotter->get_plot_width_adj();
pos = track->m_Start;
end = track->m_End;
......@@ -991,11 +1009,14 @@ void PCB_BASE_FRAME::PlotDrillMark( PLOTTER* aPlotter,
pos = pts->m_Start;
// It is quite possible that the real drill value is less then small drill value.
if( g_PcbPlotOptions.m_DrillShapeOpt == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE )
diam.x = diam.y = SMALL_DRILL;
diam.x = diam.y = MIN( SMALL_DRILL, pts->GetDrillValue() );
else
diam.x = diam.y = pts->GetDrillValue();
diam.x -= aPlotter->get_plot_width_adj();
diam.x = doIntValueFitToBand( diam.x, 1, pts->m_Width - 1 );
aPlotter->flash_pad_circle( pos, diam.x, aTraceMode );
}
......@@ -1012,11 +1033,18 @@ void PCB_BASE_FRAME::PlotDrillMark( PLOTTER* aPlotter,
if( PtPad->m_DrillShape == PAD_OVAL )
{
diam = PtPad->m_Drill;
diam.x -= aPlotter->get_plot_width_adj();
diam.x = doIntValueFitToBand( diam.x, 1, PtPad->m_Size.x - 1 );
diam.y -= aPlotter->get_plot_width_adj();
diam.y = doIntValueFitToBand( diam.y, 1, PtPad->m_Size.y - 1 );
aPlotter->flash_pad_oval( pos, diam, PtPad->m_Orient, aTraceMode );
}
else
{
diam.x = aSmallDrillShape ? SMALL_DRILL : PtPad->m_Drill.x;
// It is quite possible that the real pad drill value is less then small drill value.
diam.x = aSmallDrillShape ? MIN( SMALL_DRILL, PtPad->m_Drill.x ) : PtPad->m_Drill.x;
diam.x -= aPlotter->get_plot_width_adj();
diam.x = doIntValueFitToBand( diam.x, 1, PtPad->m_Size.x - 1 );
aPlotter->flash_pad_circle( pos, diam.x, aTraceMode );
}
}
......
......@@ -106,6 +106,7 @@ bool PCB_BASE_FRAME::ExportToPostScriptFile( const wxString& aFullFileName, int
plotter->set_scale_adjust( g_PcbPlotOptions.m_FineScaleAdjustX,
g_PcbPlotOptions.m_FineScaleAdjustY );
plotter->set_plot_width_adj( g_PcbPlotOptions.m_FineWidthAdjust );
plotter->set_viewport( offset, scale, g_PcbPlotOptions.m_PlotMirror );
plotter->set_default_line_width( g_PcbPlotOptions.m_PlotLineWidth );
plotter->set_creator( wxT( "PCBNEW-PS" ) );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment