Add "scale" option to "pcb export plotter" CLI and JOB

- Not for gerbers
- DXF, HPGL, PDF, PS and SVG
- Remove the GUI limitation that prevented the use of border & title when
  using a scale != 1
This commit is contained in:
Salvador E. Tropea 2025-04-29 07:23:57 -03:00 committed by jean-pierre charras
parent 71f71641c2
commit 1c07703851
21 changed files with 127 additions and 32 deletions

View File

@ -43,6 +43,7 @@ JOB_EXPORT_PCB_DXF::JOB_EXPORT_PCB_DXF() :
{
m_plotDrawingSheet = false;
m_params.emplace_back( new JOB_PARAM<double>( "scale", &m_scale, m_scale ) );
m_params.emplace_back( new JOB_PARAM<bool>( "plot_graphic_items_using_contours",
&m_plotGraphicItemsUsingContours,
m_plotGraphicItemsUsingContours ) );

View File

@ -39,6 +39,7 @@ JOB_EXPORT_PCB_HPGL::JOB_EXPORT_PCB_HPGL() :
m_params.emplace_back( new JOB_PARAM<wxString>( "color_theme",
&m_colorTheme, m_colorTheme ) );
m_params.emplace_back( new JOB_PARAM<GEN_MODE>( "gen_mode", &m_genMode, m_genMode ) );
m_params.emplace_back( new JOB_PARAM<double>( "scale", &m_scale, m_scale ) );
m_params.emplace_back( new JOB_PARAM<double>( "default_pen_size",
&m_defaultPenSize, m_defaultPenSize ) );
m_params.emplace_back( new JOB_PARAM<int>( "pen_speed", &m_penSpeed, m_penSpeed ) );

View File

@ -37,6 +37,7 @@ JOB_EXPORT_PCB_PDF::JOB_EXPORT_PCB_PDF() :
{
m_plotDrawingSheet = false;
m_params.emplace_back( new JOB_PARAM<double>( "scale", &m_scale, m_scale ) );
m_params.emplace_back( new JOB_PARAM<wxString>( "color_theme",
&m_colorTheme, m_colorTheme ) );

View File

@ -36,6 +36,7 @@ JOB_EXPORT_PCB_PLOT::JOB_EXPORT_PCB_PLOT( PLOT_FORMAT aFormat, const std::string
m_mirror( false ),
m_blackAndWhite( false ),
m_negative( false ),
m_scale( 1.0 ),
m_sketchPadsOnFabLayers( false ),
m_hideDNPFPsOnFabLayers( false ),
m_sketchDNPFPsOnFabLayers( true ),

View File

@ -58,6 +58,7 @@ public:
bool m_mirror;
bool m_blackAndWhite;
bool m_negative;
double m_scale;
bool m_sketchPadsOnFabLayers;
bool m_hideDNPFPsOnFabLayers;

View File

@ -38,6 +38,7 @@ JOB_EXPORT_PCB_PS::JOB_EXPORT_PCB_PS() :
{
m_plotDrawingSheet = false;
m_params.emplace_back( new JOB_PARAM<double>( "scale", &m_scale, m_scale ) );
m_params.emplace_back( new JOB_PARAM<wxString>( "color_theme",
&m_colorTheme, m_colorTheme ) );
m_params.emplace_back( new JOB_PARAM<GEN_MODE>( "gen_mode", &m_genMode, m_genMode ) );

View File

@ -36,6 +36,7 @@ JOB_EXPORT_PCB_SVG::JOB_EXPORT_PCB_SVG() :
{
m_plotDrawingSheet = true;
m_params.emplace_back( new JOB_PARAM<double>( "scale", &m_scale, m_scale ) );
m_params.emplace_back( new JOB_PARAM<wxString>( "color_theme", &m_colorTheme, m_colorTheme ) );
m_params.emplace_back(
new JOB_PARAM<bool>( "fit_page_to_board", &m_fitPageToBoard, m_fitPageToBoard ) );

View File

@ -65,6 +65,9 @@ namespace CLI
#define ARG_COMMON_LAYERS "--common-layers"
#define ARG_SCALE "--scale"
#define ARG_SCALE_DESC "Scale for the PCB, not for the border and title. Use 0 for autoscale"
struct PCB_EXPORT_BASE_COMMAND : public COMMAND
{
PCB_EXPORT_BASE_COMMAND( const std::string& aName, bool aInputCanBeDir = false,

View File

@ -110,6 +110,12 @@ CLI::PCB_EXPORT_DXF_COMMAND::PCB_EXPORT_DXF_COMMAND() :
m_argParser.add_argument( DEPRECATED_ARG_PLOT_INVISIBLE_TEXT )
.help( UTF8STDSTR( _( DEPRECATED_ARG_PLOT_INVISIBLE_TEXT_DESC ) ) )
.flag();
m_argParser.add_argument( ARG_SCALE )
.help( UTF8STDSTR( _( ARG_SCALE_DESC ) ) )
.scan<'g', double>()
.default_value( 1.0 )
.metavar( "SCALE" );
}
@ -139,6 +145,7 @@ int CLI::PCB_EXPORT_DXF_COMMAND::doPerform( KIWAY& aKiway )
dxfJob->m_useDrillOrigin = m_argParser.get<bool>( ARG_USE_DRILL_ORIGIN );
dxfJob->m_plotDrawingSheet = m_argParser.get<bool>( ARG_INCLUDE_BORDER_TITLE );
dxfJob->m_subtractSolderMaskFromSilk = m_argParser.get<bool>( ARG_SUBTRACT_SOLDERMASK );
dxfJob->m_scale = m_argParser.get<double>( ARG_SCALE );
if( m_argParser.get<bool>( DEPRECATED_ARG_PLOT_INVISIBLE_TEXT ) )
wxFprintf( stdout, DEPRECATED_ARD_PLOT_INVISIBLE_TEXT_WARNING );

View File

@ -98,6 +98,12 @@ CLI::PCB_EXPORT_HPGL_COMMAND::PCB_EXPORT_HPGL_COMMAND() :
"which files may be output." ) ) )
.flag();
m_argParser.add_argument( ARG_SCALE )
.help( UTF8STDSTR( _( ARG_SCALE_DESC ) ) )
.scan<'g', double>()
.default_value( 1.0 )
.metavar( "SCALE" );
m_argParser.add_argument( "-P", ARG_DEFAULT_PEN_SIZE )
.help( UTF8STDSTR( _( "Size for the default pen [mm]" ) ) )
.scan<'g', double>()
@ -159,6 +165,7 @@ int CLI::PCB_EXPORT_HPGL_COMMAND::doPerform( KIWAY& aKiway )
else if( m_argParser.get<bool>( ARG_MODE_SINGLE ) )
hpglJob->m_genMode = JOB_EXPORT_PCB_HPGL::GEN_MODE::SINGLE;
hpglJob->m_scale = m_argParser.get<double>( ARG_SCALE );
hpglJob->m_defaultPenSize = m_argParser.get<double>( ARG_DEFAULT_PEN_SIZE );
hpglJob->m_penNumber = m_argParser.get<int>( ARG_PEN_NUMBER );
hpglJob->m_penSpeed = m_argParser.get<int>( ARG_PEN_SPEED );

View File

@ -113,6 +113,12 @@ CLI::PCB_EXPORT_PDF_COMMAND::PCB_EXPORT_PDF_COMMAND() :
m_argParser.add_argument( ARG_MODE_MULTIPAGE )
.help( UTF8STDSTR( _( "Plot the layers to a single PDF file with multiple pages" ) ) )
.flag();
m_argParser.add_argument( ARG_SCALE )
.help( UTF8STDSTR( _( ARG_SCALE_DESC ) ) )
.scan<'g', double>()
.default_value( 1.0 )
.metavar( "SCALE" );
}
@ -144,6 +150,7 @@ int CLI::PCB_EXPORT_PDF_COMMAND::doPerform( KIWAY& aKiway )
pdfJob->m_blackAndWhite = m_argParser.get<bool>( ARG_BLACKANDWHITE );
pdfJob->m_colorTheme = From_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
pdfJob->m_negative = m_argParser.get<bool>( ARG_NEGATIVE );
pdfJob->m_scale = m_argParser.get<double>( ARG_SCALE );
pdfJob->m_sketchPadsOnFabLayers = m_argParser.get<bool>( ARG_SKETCH_PADS_ON_FAB_LAYERS );
pdfJob->m_hideDNPFPsOnFabLayers = m_argParser.get<bool>( ARG_HIDE_DNP_FPS_ON_FAB_LAYERS );

View File

@ -134,6 +134,12 @@ CLI::PCB_EXPORT_PS_COMMAND::PCB_EXPORT_PS_COMMAND() :
m_argParser.add_argument( "-A", ARG_FORCE_A4 )
.help( UTF8STDSTR( _( "Force A4 paper size." ) ) )
.flag();
m_argParser.add_argument( ARG_SCALE )
.help( UTF8STDSTR( _( ARG_SCALE_DESC ) ) )
.scan<'g', double>()
.default_value( 1.0 )
.metavar( "SCALE" );
}
@ -161,6 +167,7 @@ int CLI::PCB_EXPORT_PS_COMMAND::doPerform( KIWAY& aKiway )
psJob->m_blackAndWhite = m_argParser.get<bool>( ARG_BLACKANDWHITE );
psJob->m_colorTheme = From_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
psJob->m_negative = m_argParser.get<bool>( ARG_NEGATIVE );
psJob->m_scale = m_argParser.get<double>( ARG_SCALE );
psJob->m_sketchPadsOnFabLayers = m_argParser.get<bool>( ARG_SKETCH_PADS_ON_FAB_LAYERS );
psJob->m_hideDNPFPsOnFabLayers = m_argParser.get<bool>( ARG_HIDE_DNP_FPS_ON_FAB_LAYERS );

View File

@ -119,6 +119,12 @@ CLI::PCB_EXPORT_SVG_COMMAND::PCB_EXPORT_SVG_COMMAND() :
m_argParser.add_argument( DEPRECATED_ARG_PLOT_INVISIBLE_TEXT )
.help( UTF8STDSTR( _( DEPRECATED_ARG_PLOT_INVISIBLE_TEXT_DESC ) ) )
.flag();
m_argParser.add_argument( ARG_SCALE )
.help( UTF8STDSTR( _( ARG_SCALE_DESC ) ) )
.scan<'g', double>()
.default_value( 1.0 )
.metavar( "SCALE" );
}
@ -137,6 +143,7 @@ int CLI::PCB_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway )
svgJob->m_drillShapeOption = static_cast<DRILL_MARKS>( drillShape );
svgJob->m_drawingSheet = m_argDrawingSheet;
svgJob->m_subtractSolderMaskFromSilk = m_argParser.get<bool>( ARG_SUBTRACT_SOLDERMASK );
svgJob->m_scale = m_argParser.get<double>( ARG_SCALE );
if( m_argParser.get<bool>( DEPRECATED_ARG_PLOT_INVISIBLE_TEXT ) )
wxFprintf( stdout, DEPRECATED_ARD_PLOT_INVISIBLE_TEXT_WARNING );

View File

@ -64,6 +64,20 @@ LSET DIALOG_PLOT::s_lastAllLayersSet;
LSEQ DIALOG_PLOT::s_lastAllLayersOrder;
static double selectionToScale( int selection )
{
switch( selection )
{
default: return 1;
case 0: return 0;
case 2: return 1.5;
case 3: return 2;
case 4: return 3;
}
return 1;
}
/**
* A helper wxWidgets control client data object to store layer IDs.
*/
@ -437,7 +451,6 @@ void DIALOG_PLOT::init_Dialog()
// Update options values:
wxCommandEvent cmd_event;
SetPlotFormat( cmd_event );
OnSetScaleOpt( cmd_event );
}
@ -454,6 +467,10 @@ void DIALOG_PLOT::transferPlotParamsToJob()
gJob->m_precision = m_plotOpts.GetGerberPrecision();
gJob->m_useBoardPlotParams = false;
}
else
{
m_job->m_scale = selectionToScale( m_plotOpts.GetScaleSelection() );
}
if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::HPGL )
{
@ -780,18 +797,6 @@ void DIALOG_PLOT::OnChangeDXFPlotMode( wxCommandEvent& event )
}
void DIALOG_PLOT::OnSetScaleOpt( wxCommandEvent& event )
{
/* Disable sheet reference for scale != 1:1 */
bool scale1 = ( m_scaleOpt->GetSelection() == 1 );
m_plotSheetRef->Enable( scale1 );
if( !scale1 )
m_plotSheetRef->SetValue( false );
}
void DIALOG_PLOT::onOutputDirectoryBrowseClicked( wxCommandEvent& event )
{
// Build the absolute path of current output directory to preselect it in the file browser.
@ -881,8 +886,7 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
m_plotMirrorOpt->Enable( true );
m_useAuxOriginCheckBox->Enable( true );
m_defaultPenSize.Enable( false );
m_scaleOpt->Enable( false );
m_scaleOpt->SetSelection( 1 );
m_scaleOpt->Enable( true );
m_fineAdjustXCtrl->Enable( false );
m_fineAdjustYCtrl->Enable( false );
m_trackWidthCorrection.Enable( false );
@ -987,8 +991,7 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
m_plotMirrorOpt->SetValue( false );
m_useAuxOriginCheckBox->Enable( true );
m_defaultPenSize.Enable( false );
m_scaleOpt->Enable( false );
m_scaleOpt->SetSelection( 1 );
m_scaleOpt->Enable( true );
m_fineAdjustXCtrl->Enable( false );
m_fineAdjustYCtrl->Enable( false );
m_trackWidthCorrection.Enable( false );
@ -1011,10 +1014,6 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
break;
}
/* Update the interlock between scale and frame reference
* (scaling would mess up the frame border...) */
OnSetScaleOpt( event );
Layout();
m_MainSizer->SetSizeHints( this );
}

View File

@ -55,7 +55,6 @@ private:
void OnRightClickAllLayers( wxMouseEvent& event );
void SetPlotFormat( wxCommandEvent& event ) override;
void OnChangeDXFPlotMode( wxCommandEvent& event ) override;
void OnSetScaleOpt( wxCommandEvent& event ) override;
void CreateDrillFile( wxCommandEvent& event ) override;
void OnGerberX2Checked( wxCommandEvent& event ) override;
void onRunDRC( wxCommandEvent& event ) override;

View File

@ -483,7 +483,6 @@ DIALOG_PLOT_BASE::DIALOG_PLOT_BASE( wxWindow* parent, wxWindowID id, const wxStr
m_openDirButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_BASE::onOpenOutputDirectory ), NULL, this );
m_plotDNP->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PLOT_BASE::onDNPCheckbox ), NULL, this );
m_sketchPadsOnFabLayers->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PLOT_BASE::onSketchPads ), NULL, this );
m_scaleOpt->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PLOT_BASE::OnSetScaleOpt ), NULL, this );
m_boardSetup->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( DIALOG_PLOT_BASE::onBoardSetup ), NULL, this );
m_useGerberX2Format->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PLOT_BASE::OnGerberX2Checked ), NULL, this );
m_DXF_plotModeOpt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PLOT_BASE::OnChangeDXFPlotMode ), NULL, this );
@ -501,7 +500,6 @@ DIALOG_PLOT_BASE::~DIALOG_PLOT_BASE()
m_openDirButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_BASE::onOpenOutputDirectory ), NULL, this );
m_plotDNP->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PLOT_BASE::onDNPCheckbox ), NULL, this );
m_sketchPadsOnFabLayers->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PLOT_BASE::onSketchPads ), NULL, this );
m_scaleOpt->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PLOT_BASE::OnSetScaleOpt ), NULL, this );
m_boardSetup->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( DIALOG_PLOT_BASE::onBoardSetup ), NULL, this );
m_useGerberX2Format->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PLOT_BASE::OnGerberX2Checked ), NULL, this );
m_DXF_plotModeOpt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_PLOT_BASE::OnChangeDXFPlotMode ), NULL, this );

View File

@ -1424,7 +1424,6 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnChoice">OnSetScaleOpt</event>
</object>
</object>
<object class="gbsizeritem" expanded="false">

View File

@ -140,7 +140,6 @@ class DIALOG_PLOT_BASE : public DIALOG_SHIM
virtual void onOpenOutputDirectory( wxCommandEvent& event ) { event.Skip(); }
virtual void onDNPCheckbox( wxCommandEvent& event ) { event.Skip(); }
virtual void onSketchPads( wxCommandEvent& event ) { event.Skip(); }
virtual void OnSetScaleOpt( wxCommandEvent& event ) { event.Skip(); }
virtual void onBoardSetup( wxHyperlinkEvent& event ) { event.Skip(); }
virtual void OnGerberX2Checked( wxCommandEvent& event ) { event.Skip(); }
virtual void OnChangeDXFPlotMode( wxCommandEvent& event ) { event.Skip(); }

View File

@ -41,6 +41,29 @@
#include <math/util.h> // for KiROUND
static int scaleToSelection( double scale )
{
int selection = 1;
if( scale == 0.0 )
{
selection = 0;
}
else if( scale == 1.5 )
{
selection = 2;
}
else if( scale == 2.0 )
{
selection = 3;
}
else if( scale == 3.0 )
{
selection = 4;
}
return selection;
}
PCB_PLOTTER::PCB_PLOTTER( BOARD* aBoard, REPORTER* aReporter, PCB_PLOT_PARAMS& aParams ) :
m_board( aBoard ),
m_plotOpts( aParams ),
@ -376,6 +399,13 @@ void PCB_PLOTTER::PlotJobToPlotOpts( PCB_PLOT_PARAMS& aOpts, JOB_EXPORT_PCB_PLOT
aOpts.SetCreateGerberJobFile( gJob->m_createJobsFile );
aOpts.SetGerberPrecision( gJob->m_precision );
}
else
{
// Scale, doesn't apply to GERBER
aOpts.SetScale( aJob->m_scale );
aOpts.SetAutoScale( !aJob->m_scale );
aOpts.SetScaleSelection( scaleToSelection( aJob->m_scale ) );
}
if( aJob->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::HPGL )
{

View File

@ -162,7 +162,7 @@ PLOTTER* StartPlotBoard( BOARD* aBoard, const PCB_PLOT_PARAMS* aPlotOpts, int aL
const wxString& aPageNumber = wxEmptyString,
const int aPageCount = 1);
void setupPlotterNewPDFPage( PLOTTER* aPlotter, BOARD* aBoard, const PCB_PLOT_PARAMS* aPlotOpts,
void setupPlotterNewPDFPage( PLOTTER* aPlotter, BOARD* aBoard, PCB_PLOT_PARAMS* aPlotOpts,
const wxString& aLayerName, const wxString& aSheetName,
const wxString& aSheetPath, const wxString& aPageNumber,
int aPageCount );

View File

@ -1292,8 +1292,15 @@ PLOTTER* StartPlotBoard( BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aL
// page layout is not mirrored, so temporarily change mirror option for the page layout
PCB_PLOT_PARAMS plotOpts = *aPlotOpts;
if( plotOpts.GetPlotFrameRef() && plotOpts.GetMirror() )
plotOpts.SetMirror( false );
if( plotOpts.GetPlotFrameRef() )
{
if( plotOpts.GetMirror() )
plotOpts.SetMirror( false );
if( plotOpts.GetScale() != 1.0 )
plotOpts.SetScale( 1.0 );
if( plotOpts.GetAutoScale() )
plotOpts.SetAutoScale( false );
}
initializePlotter( plotter, aBoard, &plotOpts );
@ -1339,7 +1346,7 @@ PLOTTER* StartPlotBoard( BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aL
aPageCount, aSheetName, aSheetPath, aBoard->GetFileName(),
renderSettings->GetLayerColor( LAYER_DRAWINGSHEET ) );
if( aPlotOpts->GetMirror() )
if( aPlotOpts->GetMirror() || aPlotOpts->GetScale() != 1.0 || aPlotOpts->GetAutoScale() )
initializePlotter( plotter, aBoard, aPlotOpts );
}
@ -1362,7 +1369,7 @@ PLOTTER* StartPlotBoard( BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aL
}
void setupPlotterNewPDFPage( PLOTTER* aPlotter, BOARD* aBoard, const PCB_PLOT_PARAMS* aPlotOpts,
void setupPlotterNewPDFPage( PLOTTER* aPlotter, BOARD* aBoard, PCB_PLOT_PARAMS* aPlotOpts,
const wxString& aLayerName, const wxString& aSheetName,
const wxString& aSheetPath, const wxString& aPageNumber,
int aPageCount )
@ -1370,14 +1377,33 @@ void setupPlotterNewPDFPage( PLOTTER* aPlotter, BOARD* aBoard, const PCB_PLOT_PA
// Plot the frame reference if requested
if( aPlotOpts->GetPlotFrameRef() )
{
// Mirror and scale shouldn't be applied to the drawing sheet
bool revertOps = false;
bool oldMirror = aPlotOpts->GetMirror();
bool oldAutoScale = aPlotOpts->GetAutoScale();
double oldScale = aPlotOpts->GetScale();
if( oldMirror || oldAutoScale || oldScale != 1.0 )
{
aPlotOpts->SetMirror( false );
aPlotOpts->SetScale( 1.0 );
aPlotOpts->SetAutoScale( false );
initializePlotter( aPlotter, aBoard, aPlotOpts );
revertOps = true;
}
PlotDrawingSheet( aPlotter, aBoard->GetProject(), aBoard->GetTitleBlock(),
aBoard->GetPageSettings(), &aBoard->GetProperties(), aPageNumber,
aPageCount,
aSheetName, aSheetPath, aBoard->GetFileName(),
aPlotter->RenderSettings()->GetLayerColor( LAYER_DRAWINGSHEET ) );
if( aPlotOpts->GetMirror() )
if( revertOps )
{
aPlotOpts->SetMirror( oldMirror );
aPlotOpts->SetScale( oldScale );
aPlotOpts->SetAutoScale( oldAutoScale );
initializePlotter( aPlotter, aBoard, aPlotOpts );
}
}
aPlotter->RenderSettings()->SetLayerName( aLayerName );