From c528f3c6057f69287ef7428d95c8a34c7e2a7fe1 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Mon, 28 Apr 2025 10:09:18 -0300 Subject: [PATCH] Add HPGL job support - kicad-cli pcb export hpgl - "Export HPGL" job --- common/CMakeLists.txt | 1 + common/jobs/job_export_pcb_hpgl.cpp | 61 ++++++++++ common/jobs/job_export_pcb_hpgl.h | 51 ++++++++ kicad/CMakeLists.txt | 1 + kicad/cli/command_pcb_export_hpgl.cpp | 168 ++++++++++++++++++++++++++ kicad/cli/command_pcb_export_hpgl.h | 38 ++++++ kicad/kicad_cli.cpp | 3 + pcbnew/dialogs/dialog_plot.cpp | 12 ++ pcbnew/pcb_plotter.cpp | 9 ++ pcbnew/pcbnew_jobs_handler.cpp | 99 +++++++++++++++ pcbnew/pcbnew_jobs_handler.h | 1 + 11 files changed, 444 insertions(+) create mode 100644 common/jobs/job_export_pcb_hpgl.cpp create mode 100644 common/jobs/job_export_pcb_hpgl.h create mode 100644 kicad/cli/command_pcb_export_hpgl.cpp create mode 100644 kicad/cli/command_pcb_export_hpgl.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index ea79bb2d2d..81a1e3ba34 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -71,6 +71,7 @@ set( KICOMMON_SRCS jobs/job_export_pcb_dxf.cpp jobs/job_export_pcb_gerber.cpp jobs/job_export_pcb_gerbers.cpp + jobs/job_export_pcb_hpgl.cpp jobs/job_export_pcb_ipc2581.cpp jobs/job_export_pcb_ipcd356.cpp jobs/job_export_pcb_odb.cpp diff --git a/common/jobs/job_export_pcb_hpgl.cpp b/common/jobs/job_export_pcb_hpgl.cpp new file mode 100644 index 0000000000..84547d6d1b --- /dev/null +++ b/common/jobs/job_export_pcb_hpgl.cpp @@ -0,0 +1,61 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023 Mark Roszko + * Copyright The 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 3 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, see . + */ + +#include +#include +#include + + +NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_HPGL::GEN_MODE, + { + { JOB_EXPORT_PCB_HPGL::GEN_MODE::MULTI, "multi" }, + { JOB_EXPORT_PCB_HPGL::GEN_MODE::SINGLE, "single" }, + } ) + + +JOB_EXPORT_PCB_HPGL::JOB_EXPORT_PCB_HPGL() : + JOB_EXPORT_PCB_PLOT( JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::HPGL, "hpgl", false ), + m_genMode( GEN_MODE::MULTI ), m_defaultPenSize( 0.381 ), m_penSpeed( 20 ), m_penNumber( 1 ) +{ + m_plotDrawingSheet = false; + + m_params.emplace_back( new JOB_PARAM( "color_theme", + &m_colorTheme, m_colorTheme ) ); + m_params.emplace_back( new JOB_PARAM( "gen_mode", &m_genMode, m_genMode ) ); + m_params.emplace_back( new JOB_PARAM( "default_pen_size", + &m_defaultPenSize, m_defaultPenSize ) ); + m_params.emplace_back( new JOB_PARAM( "pen_speed", &m_penSpeed, m_penSpeed ) ); + m_params.emplace_back( new JOB_PARAM( "pen_number", &m_penNumber, m_penNumber ) ); +} + + +wxString JOB_EXPORT_PCB_HPGL::GetDefaultDescription() const +{ + return wxString::Format( _( "Export HPGL" ) ); +} + + +wxString JOB_EXPORT_PCB_HPGL::GetSettingsDialogTitle() const +{ + return wxString::Format( _( "Export HPGL Job Settings" ) ); +} + + +REGISTER_JOB( pcb_export_hpgl, _HKI( "PCB: Export HPGL" ), KIWAY::FACE_PCB, JOB_EXPORT_PCB_HPGL ); diff --git a/common/jobs/job_export_pcb_hpgl.h b/common/jobs/job_export_pcb_hpgl.h new file mode 100644 index 0000000000..d583a2d1b4 --- /dev/null +++ b/common/jobs/job_export_pcb_hpgl.h @@ -0,0 +1,51 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright The 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 3 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, see . + */ + +#ifndef JOB_EXPORT_PCB_HPGL_H +#define JOB_EXPORT_PCB_HPGL_H + +#include +#include +#include +#include +#include +#include + + +class KICOMMON_API JOB_EXPORT_PCB_HPGL : public JOB_EXPORT_PCB_PLOT +{ +public: + JOB_EXPORT_PCB_HPGL(); + wxString GetDefaultDescription() const override; + wxString GetSettingsDialogTitle() const override; + + enum class GEN_MODE + { + SINGLE, + MULTI + }; + + GEN_MODE m_genMode; + double m_defaultPenSize; + int m_penSpeed; + int m_penNumber; +}; + +#endif diff --git a/kicad/CMakeLists.txt b/kicad/CMakeLists.txt index 3bad630103..628cd4fe97 100644 --- a/kicad/CMakeLists.txt +++ b/kicad/CMakeLists.txt @@ -61,6 +61,7 @@ set( KICAD_CLI_SRCS cli/command_pcb_export_gerber.cpp cli/command_pcb_export_gerbers.cpp cli/command_pcb_export_gencad.cpp + cli/command_pcb_export_hpgl.cpp cli/command_pcb_export_ipc2581.cpp cli/command_pcb_export_ipcd356.cpp cli/command_pcb_export_odb.cpp diff --git a/kicad/cli/command_pcb_export_hpgl.cpp b/kicad/cli/command_pcb_export_hpgl.cpp new file mode 100644 index 0000000000..d9f31ebcad --- /dev/null +++ b/kicad/cli/command_pcb_export_hpgl.cpp @@ -0,0 +1,168 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright The 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 3 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, see . + */ + +#include +#include "command_pcb_export_hpgl.h" +#include +#include "jobs/job_export_pcb_hpgl.h" +#include +#include +#include + +#include + +#define ARG_MODE_SINGLE "--mode-single" +#define ARG_MODE_MULTI "--mode-multi" +#define ARG_DEFAULT_PEN_SIZE "--default-pen-size" +#define ARG_PEN_NUMBER "--pen-number" +#define ARG_PEN_SPEED "--pen-speed" + +CLI::PCB_EXPORT_HPGL_COMMAND::PCB_EXPORT_HPGL_COMMAND() : + PCB_EXPORT_BASE_COMMAND( "hpgl", false, true ) +{ + m_argParser.add_description( UTF8STDSTR( _( "Generate HPGL from a list of layers" ) ) ); + + addLayerArg(); + addCommonLayersArg(); + addDrawingSheetArg(); + addDefineArg(); + + m_argParser.add_argument( "-m", ARG_MIRROR ) + .help( UTF8STDSTR( _( "Mirror the board (useful for trying to show bottom layers)" ) ) ) + .flag(); + + m_argParser.add_argument( "--erd", ARG_EXCLUDE_REFDES ) + .help( UTF8STDSTR( _( "Exclude the reference designator text" ) ) ) + .flag(); + + m_argParser.add_argument( "--ev", ARG_EXCLUDE_VALUE ) + .help( UTF8STDSTR( _( "Exclude the value text" ) ) ) + .flag(); + + m_argParser.add_argument( "--ibt", ARG_INCLUDE_BORDER_TITLE ) + .help( UTF8STDSTR( _( "Include the border and title block" ) ) ) + .flag(); + + m_argParser.add_argument( ARG_SUBTRACT_SOLDERMASK ) + .help( UTF8STDSTR( _( "Subtract soldermask from silkscreen" ) ) ) + .flag(); + + m_argParser.add_argument( "--sp", ARG_SKETCH_PADS_ON_FAB_LAYERS ) + .help( UTF8STDSTR( _( ARG_SKETCH_PADS_ON_FAB_LAYERS_DESC ) ) ) + .flag(); + + m_argParser.add_argument( "--hdnp", ARG_HIDE_DNP_FPS_ON_FAB_LAYERS ) + .help( UTF8STDSTR( _( ARG_HIDE_DNP_FPS_ON_FAB_LAYERS_DESC ) ) ) + .flag(); + + m_argParser.add_argument( "--sdnp", ARG_SKETCH_DNP_FPS_ON_FAB_LAYERS ) + .help( UTF8STDSTR( _( ARG_SKETCH_DNP_FPS_ON_FAB_LAYERS_DESC ) ) ) + .flag(); + + m_argParser.add_argument( "--cdnp", ARG_CROSSOUT_DNP_FPS_ON_FAB_LAYERS ) + .help( UTF8STDSTR( _( ARG_CROSSOUT_DNP_FPS_ON_FAB_LAYERS_DESC ) ) ) + .flag(); + + m_argParser.add_argument( ARG_DRILL_SHAPE_OPTION ) + .help( UTF8STDSTR( _( ARG_DRILL_SHAPE_OPTION_DESC ) ) ) + .scan<'i', int>() + .default_value( 2 ); + + m_argParser.add_argument( ARG_MODE_SINGLE ) + .help( UTF8STDSTR( + _( "Generates a single file with the output arg path acting as the complete " + "directory and filename path. COMMON_LAYER_LIST does not function in this " + "mode. Instead LAYER_LIST controls all layers plotted." ) ) ) + .flag(); + + m_argParser.add_argument( ARG_MODE_MULTI ) + .help( UTF8STDSTR( _( "Generates one or more files with behavior similar to the KiCad " + "GUI plotting. The given output path specifies a directory in " + "which files may be output." ) ) ) + .flag(); + + m_argParser.add_argument( "-P", ARG_DEFAULT_PEN_SIZE ) + .help( UTF8STDSTR( _( "Size for the default pen [mm]" ) ) ) + .scan<'g', double>() + .default_value( 0.381 ) + .metavar( "DEF_SIZE" ); + + m_argParser.add_argument( "-N", ARG_PEN_NUMBER ) + .help( UTF8STDSTR( _( "Pen number selection (1 to 9)" ) ) ) + .scan<'d', int>() + .default_value( 1 ) + .metavar( "PEN_NUM" ); + + m_argParser.add_argument( "-S", ARG_PEN_SPEED ) + .help( UTF8STDSTR( _( "Pen speed [cm/s] (1 to 99 cm/s)" ) ) ) + .scan<'d', int>() + .default_value( 40 ) + .metavar( "PEN_SPD" ); +} + + +int CLI::PCB_EXPORT_HPGL_COMMAND::doPerform( KIWAY& aKiway ) +{ + std::unique_ptr hpglJob( new JOB_EXPORT_PCB_HPGL() ); + + hpglJob->m_filename = m_argInput; + hpglJob->SetConfiguredOutputPath( m_argOutput ); + hpglJob->m_drawingSheet = m_argDrawingSheet; + hpglJob->SetVarOverrides( m_argDefineVars ); + + if( !wxFile::Exists( hpglJob->m_filename ) ) + { + wxFprintf( stderr, _( "Board file does not exist or is not accessible\n" ) ); + return EXIT_CODES::ERR_INVALID_INPUT_FILE; + } + + hpglJob->m_plotFootprintValues = !m_argParser.get( ARG_EXCLUDE_VALUE ); + hpglJob->m_plotRefDes = !m_argParser.get( ARG_EXCLUDE_REFDES ); + + hpglJob->m_plotDrawingSheet = m_argParser.get( ARG_INCLUDE_BORDER_TITLE ); + hpglJob->m_subtractSolderMaskFromSilk = m_argParser.get( ARG_SUBTRACT_SOLDERMASK ); + hpglJob->m_mirror = m_argParser.get( ARG_MIRROR ); + // We don't have colors here, we just use a pen, and we don't even know its color + hpglJob->m_blackAndWhite = true; + hpglJob->m_negative = false; + + hpglJob->m_sketchPadsOnFabLayers = m_argParser.get( ARG_SKETCH_PADS_ON_FAB_LAYERS ); + hpglJob->m_hideDNPFPsOnFabLayers = m_argParser.get( ARG_HIDE_DNP_FPS_ON_FAB_LAYERS ); + hpglJob->m_sketchDNPFPsOnFabLayers = m_argParser.get( ARG_SKETCH_DNP_FPS_ON_FAB_LAYERS ); + hpglJob->m_crossoutDNPFPsOnFabLayers = m_argParser.get( ARG_CROSSOUT_DNP_FPS_ON_FAB_LAYERS ); + + int drillShape = m_argParser.get( ARG_DRILL_SHAPE_OPTION ); + hpglJob->m_drillShapeOption = static_cast( drillShape ); + + hpglJob->m_argLayers = From_UTF8( m_argParser.get( ARG_LAYERS ).c_str() ); + hpglJob->m_argCommonLayers = From_UTF8( m_argParser.get( ARG_COMMON_LAYERS ).c_str() ); + + if( m_argParser.get( ARG_MODE_MULTI ) ) + hpglJob->m_genMode = JOB_EXPORT_PCB_HPGL::GEN_MODE::MULTI; + else if( m_argParser.get( ARG_MODE_SINGLE ) ) + hpglJob->m_genMode = JOB_EXPORT_PCB_HPGL::GEN_MODE::SINGLE; + + hpglJob->m_defaultPenSize = m_argParser.get( ARG_DEFAULT_PEN_SIZE ); + hpglJob->m_penNumber = m_argParser.get( ARG_PEN_NUMBER ); + hpglJob->m_penSpeed = m_argParser.get( ARG_PEN_SPEED ); + + LOCALE_IO dummy; // Switch to "C" locale + return aKiway.ProcessJob( KIWAY::FACE_PCB, hpglJob.get() ); +} diff --git a/kicad/cli/command_pcb_export_hpgl.h b/kicad/cli/command_pcb_export_hpgl.h new file mode 100644 index 0000000000..279c8f1532 --- /dev/null +++ b/kicad/cli/command_pcb_export_hpgl.h @@ -0,0 +1,38 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright The 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 3 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, see . + */ + +#ifndef COMMAND_EXPORT_PCB_HPGL_H +#define COMMAND_EXPORT_PCB_HPGL_H + +#include "command_pcb_export_base.h" + +namespace CLI +{ +class PCB_EXPORT_HPGL_COMMAND : public PCB_EXPORT_BASE_COMMAND +{ +public: + PCB_EXPORT_HPGL_COMMAND(); + +protected: + int doPerform( KIWAY& aKiway ) override; +}; +} // namespace CLI + +#endif \ No newline at end of file diff --git a/kicad/kicad_cli.cpp b/kicad/kicad_cli.cpp index 19730eb7ea..81c71ed1f4 100644 --- a/kicad/kicad_cli.cpp +++ b/kicad/kicad_cli.cpp @@ -57,6 +57,7 @@ #include "cli/command_pcb_export_dxf.h" #include "cli/command_pcb_export_gerber.h" #include "cli/command_pcb_export_gerbers.h" +#include "cli/command_pcb_export_hpgl.h" #include "cli/command_pcb_export_gencad.h" #include "cli/command_pcb_export_ipc2581.h" #include "cli/command_pcb_export_ipcd356.h" @@ -131,6 +132,7 @@ static CLI::PCB_EXPORT_POS_COMMAND exportPcbPosCmd{}; static CLI::PCB_EXPORT_PS_COMMAND exportPcbPsCmd{}; static CLI::PCB_EXPORT_GERBER_COMMAND exportPcbGerberCmd{}; static CLI::PCB_EXPORT_GERBERS_COMMAND exportPcbGerbersCmd{}; +static CLI::PCB_EXPORT_HPGL_COMMAND exportPcbHpglCmd{}; static CLI::PCB_EXPORT_GENCAD_COMMAND exportPcbGencadCmd{}; static CLI::PCB_EXPORT_IPC2581_COMMAND exportPcbIpc2581Cmd{}; static CLI::PCB_EXPORT_IPCD356_COMMAND exportPcbIpcD356Cmd{}; @@ -199,6 +201,7 @@ static std::vector commandStack = { &exportPcbDxfCmd, &exportPcbGerberCmd, &exportPcbGerbersCmd, + &exportPcbHpglCmd, &exportPcbGencadCmd, &exportPcbGlbCmd, &exportPcbIpc2581Cmd, diff --git a/pcbnew/dialogs/dialog_plot.cpp b/pcbnew/dialogs/dialog_plot.cpp index 12ee9bf120..a16a953992 100644 --- a/pcbnew/dialogs/dialog_plot.cpp +++ b/pcbnew/dialogs/dialog_plot.cpp @@ -47,6 +47,7 @@ #include // for KiROUND #include #include +#include #include #include #include @@ -454,6 +455,15 @@ void DIALOG_PLOT::transferPlotParamsToJob() gJob->m_useBoardPlotParams = false; } + if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::HPGL ) + { + JOB_EXPORT_PCB_HPGL* hpglJob = static_cast( m_job ); + hpglJob->m_genMode = JOB_EXPORT_PCB_HPGL::GEN_MODE::MULTI; + hpglJob->m_defaultPenSize = m_plotOpts.GetHPGLPenDiameter() / 1000.0 * 25.4; // mils to mm + hpglJob->m_penNumber = m_plotOpts.GetHPGLPenNum(); + hpglJob->m_penSpeed = m_plotOpts.GetHPGLPenSpeed(); + } + if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::SVG ) { JOB_EXPORT_PCB_SVG* svgJob = static_cast( m_job ); @@ -1120,6 +1130,8 @@ void DIALOG_PLOT::applyPlotSettings() { tempOptions.SetHPGLPenDiameter( m_plotOpts.GetHPGLPenDiameter() ); } + tempOptions.SetHPGLPenSpeed( m_plotOpts.GetHPGLPenSpeed() ); + tempOptions.SetHPGLPenNum( m_plotOpts.GetHPGLPenNum() ); // X scale double tmpDouble; diff --git a/pcbnew/pcb_plotter.cpp b/pcbnew/pcb_plotter.cpp index 216ba0fb98..228b63c513 100644 --- a/pcbnew/pcb_plotter.cpp +++ b/pcbnew/pcb_plotter.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -376,6 +377,14 @@ void PCB_PLOTTER::PlotJobToPlotOpts( PCB_PLOT_PARAMS& aOpts, JOB_EXPORT_PCB_PLOT aOpts.SetGerberPrecision( gJob->m_precision ); } + if( aJob->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::HPGL ) + { + JOB_EXPORT_PCB_HPGL* hpglJob = static_cast( aJob ); + aOpts.SetHPGLPenDiameter( hpglJob->m_defaultPenSize / 25.4 * 1000.0 ); // mm to mils + aOpts.SetHPGLPenSpeed( hpglJob->m_penSpeed ); + aOpts.SetHPGLPenNum( hpglJob->m_penNumber ); + } + if( aJob->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::SVG ) { JOB_EXPORT_PCB_SVG* svgJob = static_cast( aJob ); diff --git a/pcbnew/pcbnew_jobs_handler.cpp b/pcbnew/pcbnew_jobs_handler.cpp index 74d53e3d48..2076a5d6cb 100644 --- a/pcbnew/pcbnew_jobs_handler.cpp +++ b/pcbnew/pcbnew_jobs_handler.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -221,6 +222,19 @@ PCBNEW_JOBS_HANDLER::PCBNEW_JOBS_HANDLER( KIWAY* aKiway ) : DIALOG_PLOT dlg( editFrame, aParent, gJob ); return dlg.ShowModal() == wxID_OK; } ); + Register( "hpgl", std::bind( &PCBNEW_JOBS_HANDLER::JobExportHpgl, this, std::placeholders::_1 ), + [aKiway]( JOB* job, wxWindow* aParent ) -> bool + { + JOB_EXPORT_PCB_HPGL* hpglJob = dynamic_cast( job ); + + PCB_EDIT_FRAME* editFrame = + dynamic_cast( aKiway->Player( FRAME_PCB_EDITOR, false ) ); + + wxCHECK( hpglJob && editFrame, false ); + + DIALOG_PLOT dlg( editFrame, aParent, hpglJob ); + return dlg.ShowModal() == wxID_OK; + } ); Register( "drill", std::bind( &PCBNEW_JOBS_HANDLER::JobExportDrill, this, std::placeholders::_1 ), [aKiway]( JOB* job, wxWindow* aParent ) -> bool @@ -1283,6 +1297,91 @@ int PCBNEW_JOBS_HANDLER::JobExportGerbers( JOB* aJob ) return exitCode; } + +int PCBNEW_JOBS_HANDLER::JobExportHpgl( JOB* aJob ) +{ + JOB_EXPORT_PCB_HPGL* hpglJob = dynamic_cast( aJob ); + + if( hpglJob == nullptr ) + return CLI::EXIT_CODES::ERR_UNKNOWN; + + BOARD* brd = getBoard( hpglJob->m_filename ); + + if( !brd ) + return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE; + + hpglJob->SetTitleBlock( brd->GetTitleBlock() ); + loadOverrideDrawingSheet( brd, hpglJob->m_drawingSheet ); + brd->GetProject()->ApplyTextVars( hpglJob->GetVarOverrides() ); + brd->SynchronizeProperties(); + + if( hpglJob->m_argLayers ) + hpglJob->m_plotLayerSequence = convertLayerArg( hpglJob->m_argLayers.value(), brd ); + + if( hpglJob->m_argCommonLayers ) + hpglJob->m_plotOnAllLayersSequence = convertLayerArg( hpglJob->m_argCommonLayers.value(), brd ); + + if( hpglJob->m_plotLayerSequence.size() < 1 ) + { + m_reporter->Report( _( "At least one layer must be specified\n" ), RPT_SEVERITY_ERROR ); + return CLI::EXIT_CODES::ERR_ARGS; + } + + bool isSingle = hpglJob->m_genMode == JOB_EXPORT_PCB_HPGL::GEN_MODE::SINGLE; + + if( isSingle ) + { + if( hpglJob->GetConfiguredOutputPath().IsEmpty() ) + { + wxFileName fn = brd->GetFileName(); + fn.SetName( fn.GetName() ); + fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::POST ) ); + + hpglJob->SetWorkingOutputPath( fn.GetFullName() ); + } + } + + wxString outPath = hpglJob->GetFullOutputPath( brd->GetProject() ); + + if( !PATHS::EnsurePathExists( outPath, isSingle ) ) + { + m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR ); + return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT; + } + + PCB_PLOT_PARAMS plotOpts; + PCB_PLOTTER::PlotJobToPlotOpts( plotOpts, hpglJob, *m_reporter ); + + PCB_PLOTTER pcbPlotter( brd, m_reporter, plotOpts ); + + std::optional layerName; + std::optional sheetName; + std::optional sheetPath; + + if( isSingle ) + { + if( aJob->GetVarOverrides().contains( wxT( "LAYER" ) ) ) + layerName = hpglJob->GetVarOverrides().at( wxT( "LAYER" ) ); + + if( aJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) ) + sheetName = hpglJob->GetVarOverrides().at( wxT( "SHEETNAME" ) ); + + if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) ) + sheetPath = hpglJob->GetVarOverrides().at( wxT( "SHEETPATH" ) ); + } + + LOCALE_IO dummy; + + if( !pcbPlotter.Plot( outPath, hpglJob->m_plotLayerSequence, hpglJob->m_plotOnAllLayersSequence, false, isSingle, + layerName, sheetName, sheetPath ) ) + { + return CLI::EXIT_CODES::ERR_UNKNOWN; + } + + return CLI::EXIT_CODES::OK; +} + + int PCBNEW_JOBS_HANDLER::JobExportGencad( JOB* aJob ) { JOB_EXPORT_PCB_GENCAD* aGencadJob = dynamic_cast( aJob ); diff --git a/pcbnew/pcbnew_jobs_handler.h b/pcbnew/pcbnew_jobs_handler.h index 33539efd06..2530fa9d68 100644 --- a/pcbnew/pcbnew_jobs_handler.h +++ b/pcbnew/pcbnew_jobs_handler.h @@ -44,6 +44,7 @@ public: int JobExportPs( JOB* aJob ); int JobExportGerber( JOB* aJob ); int JobExportGerbers( JOB* aJob ); + int JobExportHpgl( JOB* aJob ); int JobExportGencad( JOB* aJob ); int JobExportDrill( JOB* aJob ); int JobExportPos( JOB* aJob );