mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-19 22:51:40 +00:00
Combine/move svg plot job to single path
This commit is contained in:
parent
4dfcbc6d2a
commit
ecfc868832
@ -24,15 +24,15 @@
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_SVG::GEN_MODE,
|
||||
{
|
||||
{ JOB_EXPORT_PCB_SVG::GEN_MODE::DEPRECATED, "deprecated" },
|
||||
{ JOB_EXPORT_PCB_SVG::GEN_MODE::NEW, "new" },
|
||||
{ JOB_EXPORT_PCB_SVG::GEN_MODE::MULTI, "multi" }, // intended gui behavior, first as default
|
||||
{ JOB_EXPORT_PCB_SVG::GEN_MODE::SINGLE, "single" },
|
||||
} )
|
||||
|
||||
JOB_EXPORT_PCB_SVG::JOB_EXPORT_PCB_SVG() :
|
||||
JOB_EXPORT_PCB_PLOT( JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::SVG, "svg", false ),
|
||||
m_pageSizeMode( 0 ),
|
||||
m_precision( 4 ),
|
||||
m_genMode( GEN_MODE::NEW )
|
||||
m_genMode( GEN_MODE::SINGLE )
|
||||
{
|
||||
m_plotDrawingSheet = true;
|
||||
|
||||
@ -48,7 +48,6 @@ JOB_EXPORT_PCB_SVG::JOB_EXPORT_PCB_SVG() :
|
||||
m_params.emplace_back(
|
||||
new JOB_PARAM<DRILL_MARKS>( "drill_shape", &m_drillShapeOption, m_drillShapeOption ) );
|
||||
m_params.emplace_back( new JOB_PARAM<unsigned int>( "precision", &m_precision, m_precision ) );
|
||||
|
||||
m_params.emplace_back( new JOB_PARAM<GEN_MODE>( "gen_mode", &m_genMode, m_genMode ) );
|
||||
}
|
||||
|
||||
|
@ -40,8 +40,8 @@ public:
|
||||
|
||||
enum class GEN_MODE
|
||||
{
|
||||
DEPRECATED,
|
||||
NEW
|
||||
SINGLE,
|
||||
MULTI
|
||||
};
|
||||
|
||||
GEN_MODE m_genMode;
|
||||
|
@ -32,7 +32,8 @@
|
||||
|
||||
#define ARG_EXCLUDE_DRAWING_SHEET "--exclude-drawing-sheet"
|
||||
#define ARG_PAGE_SIZE "--page-size-mode"
|
||||
#define ARG_MODE_NEW "--mode-new"
|
||||
#define ARG_MODE_SINGLE "--mode-single"
|
||||
#define ARG_MODE_MULTI "--mode-multi"
|
||||
|
||||
CLI::PCB_EXPORT_SVG_COMMAND::PCB_EXPORT_SVG_COMMAND() : PCB_EXPORT_BASE_COMMAND( "svg" )
|
||||
{
|
||||
@ -100,10 +101,18 @@ CLI::PCB_EXPORT_SVG_COMMAND::PCB_EXPORT_SVG_COMMAND() : PCB_EXPORT_BASE_COMMAND(
|
||||
"F.Cu,B.Cu" ) ) )
|
||||
.metavar( "COMMON_LAYER_LIST" );
|
||||
|
||||
m_argParser.add_argument( ARG_MODE_NEW )
|
||||
|
||||
m_argParser.add_argument( ARG_MODE_SINGLE )
|
||||
.help( UTF8STDSTR(
|
||||
_( "Opt into the new behavior which means output path is a directory, a file "
|
||||
"per layer is generated and the common layers arg becomes available. " ) ) )
|
||||
_( "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();
|
||||
|
||||
|
||||
@ -152,19 +161,19 @@ int CLI::PCB_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway )
|
||||
|
||||
svgJob->m_printMaskLayer = m_selectedLayers;
|
||||
|
||||
if( m_argParser.get<bool>( ARG_MODE_NEW ) )
|
||||
svgJob->m_genMode = JOB_EXPORT_PCB_SVG::GEN_MODE::NEW;
|
||||
if( m_argParser.get<bool>( ARG_MODE_MULTI ) )
|
||||
svgJob->m_genMode = JOB_EXPORT_PCB_SVG::GEN_MODE::MULTI;
|
||||
else
|
||||
svgJob->m_genMode = JOB_EXPORT_PCB_SVG::GEN_MODE::DEPRECATED;
|
||||
svgJob->m_genMode = JOB_EXPORT_PCB_SVG::GEN_MODE::SINGLE;
|
||||
|
||||
if( svgJob->m_genMode == JOB_EXPORT_PCB_SVG::GEN_MODE::DEPRECATED )
|
||||
if( svgJob->m_genMode == JOB_EXPORT_PCB_SVG::GEN_MODE::SINGLE )
|
||||
{
|
||||
wxFprintf( stdout, wxT( "\033[33;1m%s\033[0m\n" ),
|
||||
_( "This command has deprecated behavior as of KiCad 9.0, the default behavior "
|
||||
"of this command will change in a future release." ) );
|
||||
|
||||
wxFprintf( stdout, wxT( "\033[33;1m%s\033[0m\n" ),
|
||||
_( "The new behavior will match --mode-new" ) );
|
||||
_( "The new behavior will match --mode-multi" ) );
|
||||
}
|
||||
|
||||
int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, svgJob.get() );
|
||||
|
@ -453,6 +453,7 @@ void DIALOG_PLOT::transferPlotParamsToJob()
|
||||
{
|
||||
JOB_EXPORT_PCB_SVG* svgJob = static_cast<JOB_EXPORT_PCB_SVG*>( m_job );
|
||||
svgJob->m_precision = m_plotOpts.GetSvgPrecision();
|
||||
svgJob->m_genMode = JOB_EXPORT_PCB_SVG::GEN_MODE::MULTI;
|
||||
}
|
||||
|
||||
if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::DXF )
|
||||
@ -463,6 +464,7 @@ void DIALOG_PLOT::transferPlotParamsToJob()
|
||||
: JOB_EXPORT_PCB_DXF::DXF_UNITS::MILLIMETERS;
|
||||
dxfJob->m_plotGraphicItemsUsingContours = m_plotOpts.GetPlotMode() == OUTLINE_MODE::SKETCH;
|
||||
dxfJob->m_polygonMode = m_plotOpts.GetDXFPlotPolygonMode();
|
||||
dxfJob->m_genMode = JOB_EXPORT_PCB_DXF::GEN_MODE::NEW;
|
||||
}
|
||||
|
||||
if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::PDF )
|
||||
|
@ -44,8 +44,14 @@ PCB_PLOTTER::PCB_PLOTTER( BOARD* aBoard, REPORTER* aReporter, PCB_PLOT_PARAMS& a
|
||||
}
|
||||
|
||||
|
||||
bool PCB_PLOTTER::Plot( const wxString& aOutputPath, const LSEQ& aLayersToPlot,
|
||||
const LSEQ& aCommonLayers, bool aUseGerberFileExtensions )
|
||||
bool PCB_PLOTTER::Plot( const wxString& aOutputPath,
|
||||
const LSEQ& aLayersToPlot,
|
||||
const LSEQ& aCommonLayers,
|
||||
bool aUseGerberFileExtensions,
|
||||
bool aOutputPathIsSingle,
|
||||
std::optional<wxString> aLayerName,
|
||||
std::optional<wxString> aSheetName,
|
||||
std::optional<wxString> aSheetPath )
|
||||
{
|
||||
std::function<bool( wxString* )> textResolver = [&]( wxString* token ) -> bool
|
||||
{
|
||||
@ -53,10 +59,34 @@ bool PCB_PLOTTER::Plot( const wxString& aOutputPath, const LSEQ& aLayersToPlot,
|
||||
return m_board->ResolveTextVar( token, 0 );
|
||||
};
|
||||
|
||||
size_t finalPageCount = 0;
|
||||
for( size_t i = 0; i < aLayersToPlot.size(); i++ )
|
||||
// sanity, ensure one layer to print
|
||||
if( aLayersToPlot.size() < 1 )
|
||||
{
|
||||
PCB_LAYER_ID layer = aLayersToPlot[i];
|
||||
m_reporter->Report( _( "No layers selected for plotting." ), RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
}
|
||||
|
||||
// To reuse logic, in single plot mode, we want to kick any extra layers from the main list to commonLayers
|
||||
LSEQ layersToPlot;
|
||||
LSEQ commonLayers;
|
||||
if( aOutputPathIsSingle )
|
||||
{
|
||||
layersToPlot.push_back( aLayersToPlot[0] );
|
||||
|
||||
if( aLayersToPlot.size() > 1 )
|
||||
commonLayers.insert( commonLayers.end(), aLayersToPlot.begin() + 1,
|
||||
aLayersToPlot.end() );
|
||||
}
|
||||
else
|
||||
{
|
||||
layersToPlot = aLayersToPlot;
|
||||
commonLayers = aCommonLayers;
|
||||
}
|
||||
|
||||
size_t finalPageCount = 0;
|
||||
for( size_t i = 0; i < layersToPlot.size(); i++ )
|
||||
{
|
||||
PCB_LAYER_ID layer = layersToPlot[i];
|
||||
if( copperLayerShouldBeSkipped( layer ) )
|
||||
continue;
|
||||
|
||||
@ -65,45 +95,53 @@ bool PCB_PLOTTER::Plot( const wxString& aOutputPath, const LSEQ& aLayersToPlot,
|
||||
|
||||
std::unique_ptr<GERBER_JOBFILE_WRITER> jobfile_writer;
|
||||
|
||||
if( m_plotOpts.GetFormat() == PLOT_FORMAT::GERBER )
|
||||
if( m_plotOpts.GetFormat() == PLOT_FORMAT::GERBER && !aOutputPathIsSingle )
|
||||
{
|
||||
jobfile_writer = std::make_unique<GERBER_JOBFILE_WRITER>( m_board, m_reporter );
|
||||
}
|
||||
|
||||
wxString fileExt( GetDefaultPlotExtension( m_plotOpts.GetFormat() ) );
|
||||
wxString sheetPath;
|
||||
wxString msg;
|
||||
PLOTTER* plotter = nullptr;
|
||||
for( size_t i = 0, pageNum = 1; i < aLayersToPlot.size(); i++ )
|
||||
for( size_t i = 0, pageNum = 1; i < layersToPlot.size(); i++ )
|
||||
{
|
||||
PCB_LAYER_ID layer = aLayersToPlot[i];
|
||||
PCB_LAYER_ID layer = layersToPlot[i];
|
||||
|
||||
if( copperLayerShouldBeSkipped( layer ) )
|
||||
continue;
|
||||
|
||||
LSEQ plotSequence = getPlotSequence( layer, aCommonLayers );
|
||||
LSEQ plotSequence = getPlotSequence( layer, commonLayers );
|
||||
|
||||
wxString layerName = m_board->GetLayerName( layer );
|
||||
|
||||
wxFileName fn;
|
||||
wxFileName brdFn = m_board->GetFileName();
|
||||
wxString msg;
|
||||
fn.Assign( aOutputPath, brdFn.GetName() );
|
||||
|
||||
// Use Gerber Extensions based on layer number
|
||||
// (See http://en.wikipedia.org/wiki/Gerber_File)
|
||||
if( m_plotOpts.GetFormat() == PLOT_FORMAT::GERBER && aUseGerberFileExtensions )
|
||||
fileExt = GetGerberProtelExtension( layer );
|
||||
|
||||
if( m_plotOpts.GetFormat() == PLOT_FORMAT::PDF && m_plotOpts.m_PDFSingle )
|
||||
if( aOutputPathIsSingle )
|
||||
{
|
||||
fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::PDF ) );
|
||||
fn = wxFileName( aOutputPath );
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildPlotFileName( &fn, aOutputPath, layerName, fileExt );
|
||||
wxFileName brdFn = m_board->GetFileName();
|
||||
fn.Assign( aOutputPath, brdFn.GetName() );
|
||||
|
||||
// Use Gerber Extensions based on layer number
|
||||
// (See http://en.wikipedia.org/wiki/Gerber_File)
|
||||
if( m_plotOpts.GetFormat() == PLOT_FORMAT::GERBER && aUseGerberFileExtensions )
|
||||
fileExt = GetGerberProtelExtension( layer );
|
||||
|
||||
if( m_plotOpts.GetFormat() == PLOT_FORMAT::PDF && m_plotOpts.m_PDFSingle )
|
||||
{
|
||||
fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::PDF ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildPlotFileName( &fn, aOutputPath, layerName, fileExt );
|
||||
}
|
||||
}
|
||||
|
||||
if( m_plotOpts.GetFormat() == PLOT_FORMAT::GERBER )
|
||||
if( jobfile_writer )
|
||||
{
|
||||
wxString fullname = fn.GetFullName();
|
||||
jobfile_writer->AddGbrFile( layer, fullname );
|
||||
@ -119,6 +157,18 @@ bool PCB_PLOTTER::Plot( const wxString& aOutputPath, const LSEQ& aLayersToPlot,
|
||||
wxString pageName = layerName;
|
||||
wxString sheetName = layerName;
|
||||
|
||||
if( aLayerName.has_value() )
|
||||
{
|
||||
layerName = aLayerName.value();
|
||||
pageName = aLayerName.value();
|
||||
}
|
||||
|
||||
if( aSheetName.has_value() )
|
||||
sheetName = aSheetName.value();
|
||||
|
||||
if( aSheetPath.has_value() )
|
||||
sheetPath = aSheetPath.value();
|
||||
|
||||
plotter = StartPlotBoard( m_board, &m_plotOpts, layer, layerName, fn.GetFullPath(),
|
||||
sheetName,
|
||||
sheetPath, pageName, pageNumber, finalPageCount );
|
||||
@ -146,7 +196,7 @@ bool PCB_PLOTTER::Plot( const wxString& aOutputPath, const LSEQ& aLayersToPlot,
|
||||
|
||||
|
||||
if( m_plotOpts.GetFormat() == PLOT_FORMAT::PDF && m_plotOpts.m_PDFSingle
|
||||
&& i != aLayersToPlot.size() - 1 )
|
||||
&& i != layersToPlot.size() - 1 )
|
||||
{
|
||||
wxString pageNumber = wxString::Format( "%zu", pageNum + 1 );
|
||||
|
||||
@ -156,9 +206,9 @@ bool PCB_PLOTTER::Plot( const wxString& aOutputPath, const LSEQ& aLayersToPlot,
|
||||
do
|
||||
{
|
||||
++nextI;
|
||||
nextLayer = aLayersToPlot[nextI];
|
||||
nextLayer = layersToPlot[nextI];
|
||||
} while( copperLayerShouldBeSkipped( nextLayer )
|
||||
&& ( nextI < aLayersToPlot.size() - 1 ) );
|
||||
&& ( nextI < layersToPlot.size() - 1 ) );
|
||||
|
||||
wxString pageName = m_board->GetLayerName( nextLayer );
|
||||
wxString sheetName = layerName;
|
||||
@ -202,7 +252,7 @@ bool PCB_PLOTTER::Plot( const wxString& aOutputPath, const LSEQ& aLayersToPlot,
|
||||
wxSafeYield(); // displays report message.
|
||||
}
|
||||
|
||||
if( m_plotOpts.GetFormat() == PLOT_FORMAT::GERBER && m_plotOpts.GetCreateGerberJobFile() )
|
||||
if( jobfile_writer && m_plotOpts.GetCreateGerberJobFile() )
|
||||
{
|
||||
// Pick the basename from the board file
|
||||
wxFileName fn( m_board->GetFileName() );
|
||||
|
@ -36,7 +36,11 @@ public:
|
||||
PCB_PLOTTER( BOARD* aBoard, REPORTER* aReporter, PCB_PLOT_PARAMS& aParams );
|
||||
|
||||
bool Plot( const wxString& aOutputPath, const LSEQ& aLayersToPlot, const LSEQ& aCommonLayers,
|
||||
bool aUseGerberFileExtensions );
|
||||
bool aUseGerberFileExtensions,
|
||||
bool aOutputPathIsSingle = false,
|
||||
std::optional<wxString> aLayerName = std::nullopt,
|
||||
std::optional<wxString> aSheetName = std::nullopt,
|
||||
std::optional<wxString> aSheetPath = std::nullopt );
|
||||
|
||||
/**
|
||||
* All copper layers that are disabled are actually selected
|
||||
|
@ -702,60 +702,35 @@ int PCBNEW_JOBS_HANDLER::JobExportSvg( JOB* aJob )
|
||||
brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
|
||||
brd->SynchronizeProperties();
|
||||
|
||||
if( aSvgJob->m_genMode == JOB_EXPORT_PCB_SVG::GEN_MODE::DEPRECATED )
|
||||
PCB_PLOT_PARAMS plotOpts;
|
||||
PCB_PLOTTER::PlotJobToPlotOpts( plotOpts, aSvgJob );
|
||||
|
||||
PCB_PLOTTER plotter( brd, m_reporter, plotOpts );
|
||||
|
||||
std::optional<wxString> layerName;
|
||||
std::optional<wxString> sheetName;
|
||||
std::optional<wxString> sheetPath;
|
||||
|
||||
if( aSvgJob->m_genMode == JOB_EXPORT_PCB_SVG::GEN_MODE::SINGLE )
|
||||
{
|
||||
PCB_PLOT_SVG_OPTIONS svgPlotOptions;
|
||||
svgPlotOptions.m_blackAndWhite = aSvgJob->m_blackAndWhite;
|
||||
svgPlotOptions.m_colorTheme = aSvgJob->m_colorTheme;
|
||||
svgPlotOptions.m_outputFile = aSvgJob->GetFullOutputPath();
|
||||
svgPlotOptions.m_mirror = aSvgJob->m_mirror;
|
||||
svgPlotOptions.m_negative = aSvgJob->m_negative;
|
||||
svgPlotOptions.m_pageSizeMode = aSvgJob->m_pageSizeMode;
|
||||
svgPlotOptions.m_printMaskLayer = aSvgJob->m_printMaskLayer;
|
||||
svgPlotOptions.m_plotFrame = aSvgJob->m_plotDrawingSheet;
|
||||
svgPlotOptions.m_sketchPadsOnFabLayers = aSvgJob->m_sketchPadsOnFabLayers;
|
||||
svgPlotOptions.m_hideDNPFPsOnFabLayers = aSvgJob->m_hideDNPFPsOnFabLayers;
|
||||
svgPlotOptions.m_sketchDNPFPsOnFabLayers = aSvgJob->m_sketchDNPFPsOnFabLayers;
|
||||
svgPlotOptions.m_crossoutDNPFPsOnFabLayers = aSvgJob->m_crossoutDNPFPsOnFabLayers;
|
||||
svgPlotOptions.m_precision = aSvgJob->m_precision;
|
||||
if( aJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
|
||||
layerName = aSvgJob->GetVarOverrides().at( wxT( "LAYER" ) );
|
||||
|
||||
switch( aSvgJob->m_drillShapeOption )
|
||||
{
|
||||
default:
|
||||
case JOB_EXPORT_PCB_PLOT::DRILL_MARKS::NO_DRILL_SHAPE:
|
||||
svgPlotOptions.m_drillShapeOption = static_cast<int>( DRILL_MARKS::NO_DRILL_SHAPE );
|
||||
break;
|
||||
case JOB_EXPORT_PCB_PLOT::DRILL_MARKS::SMALL_DRILL_SHAPE:
|
||||
svgPlotOptions.m_drillShapeOption = static_cast<int>( DRILL_MARKS::SMALL_DRILL_SHAPE );
|
||||
break;
|
||||
case JOB_EXPORT_PCB_PLOT::DRILL_MARKS::FULL_DRILL_SHAPE:
|
||||
svgPlotOptions.m_drillShapeOption = static_cast<int>( DRILL_MARKS::FULL_DRILL_SHAPE );
|
||||
break;
|
||||
}
|
||||
if( aJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
|
||||
sheetName = aSvgJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
|
||||
|
||||
if( EXPORT_SVG::Plot( brd, svgPlotOptions ) )
|
||||
{
|
||||
m_reporter->Report( _( "Successfully created svg file" ) + wxS( "\n" ),
|
||||
RPT_SEVERITY_INFO );
|
||||
return CLI::EXIT_CODES::OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_reporter->Report( _( "Error creating svg file" ) + wxS( "\n" ), RPT_SEVERITY_ERROR );
|
||||
return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
|
||||
}
|
||||
if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
|
||||
sheetPath = aSvgJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
PCB_PLOT_PARAMS plotOpts;
|
||||
PCB_PLOTTER::PlotJobToPlotOpts( plotOpts, aSvgJob );
|
||||
|
||||
PCB_PLOTTER plotter( brd, m_reporter, plotOpts );
|
||||
if( !plotter.Plot( aSvgJob->GetFullOutputPath(), aSvgJob->m_printMaskLayer,
|
||||
aSvgJob->m_printMaskLayersToIncludeOnAllLayers, false ) )
|
||||
{
|
||||
return CLI::EXIT_CODES::ERR_UNKNOWN;
|
||||
}
|
||||
if( !plotter.Plot( aSvgJob->GetFullOutputPath(), aSvgJob->m_printMaskLayer,
|
||||
aSvgJob->m_printMaskLayersToIncludeOnAllLayers, false,
|
||||
aSvgJob->m_genMode == JOB_EXPORT_PCB_SVG::GEN_MODE::SINGLE,
|
||||
layerName,
|
||||
sheetName,
|
||||
sheetPath ) )
|
||||
{
|
||||
return CLI::EXIT_CODES::ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
return CLI::EXIT_CODES::OK;
|
||||
|
Loading…
Reference in New Issue
Block a user