From b60c42ea4187d5ae0321caa77bdd724e59a9ac1b Mon Sep 17 00:00:00 2001 From: Marek Roszko Date: Wed, 26 Oct 2022 17:59:33 -0400 Subject: [PATCH] Add schematic cli plotting --- common/jobs/job_export_sch_pdf.h | 46 + common/jobs/job_export_sch_svg.h | 46 + eeschema/CMakeLists.txt | 5 +- eeschema/dialogs/dialog_plot_schematic.cpp | 911 +---------------- eeschema/dialogs/dialog_plot_schematic.h | 72 +- eeschema/eeschema.cpp | 11 +- eeschema/eeschema_helpers.cpp | 154 +++ eeschema/eeschema_helpers.h | 56 ++ eeschema/eeschema_jobs_handler.cpp | 111 ++ eeschema/eeschema_jobs_handler.h | 57 ++ eeschema/sch_edit_frame.cpp | 16 - eeschema/sch_edit_frame.h | 9 - eeschema/sch_plotter.cpp | 1055 ++++++++++++++++++++ eeschema/sch_plotter.h | 221 ++++ eeschema/schematic.cpp | 16 + eeschema/schematic.h | 9 + kicad/CMakeLists.txt | 4 + kicad/cli/command_export_sch_pdf.cpp | 78 ++ kicad/cli/command_export_sch_pdf.h | 37 + kicad/cli/command_export_sch_svg.cpp | 78 ++ kicad/cli/command_export_sch_svg.h | 37 + kicad/cli/command_sch.cpp | 32 + kicad/cli/command_sch.h | 36 + kicad/cli/command_sch_export.cpp | 33 + kicad/cli/command_sch_export.h | 36 + kicad/kicad_cli.cpp | 21 +- 26 files changed, 2204 insertions(+), 983 deletions(-) create mode 100644 common/jobs/job_export_sch_pdf.h create mode 100644 common/jobs/job_export_sch_svg.h create mode 100644 eeschema/eeschema_helpers.cpp create mode 100644 eeschema/eeschema_helpers.h create mode 100644 eeschema/eeschema_jobs_handler.cpp create mode 100644 eeschema/eeschema_jobs_handler.h create mode 100644 eeschema/sch_plotter.cpp create mode 100644 eeschema/sch_plotter.h create mode 100644 kicad/cli/command_export_sch_pdf.cpp create mode 100644 kicad/cli/command_export_sch_pdf.h create mode 100644 kicad/cli/command_export_sch_svg.cpp create mode 100644 kicad/cli/command_export_sch_svg.h create mode 100644 kicad/cli/command_sch.cpp create mode 100644 kicad/cli/command_sch.h create mode 100644 kicad/cli/command_sch_export.cpp create mode 100644 kicad/cli/command_sch_export.h diff --git a/common/jobs/job_export_sch_pdf.h b/common/jobs/job_export_sch_pdf.h new file mode 100644 index 0000000000..5046fd9987 --- /dev/null +++ b/common/jobs/job_export_sch_pdf.h @@ -0,0 +1,46 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright (C) 1992-2022 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_SCH_PDF_H +#define JOB_EXPORT_SCH_PDF_H + +#include +#include "job.h" + +class JOB_EXPORT_SCH_PDF : public JOB +{ +public: + JOB_EXPORT_SCH_PDF( bool aIsCli ) : + JOB( "pdf", aIsCli ), + m_filename(), + m_outputFile() + { + } + + wxString m_filename; + wxString m_outputFile; + wxString m_colorTheme; + + bool m_blackAndWhite; + bool m_useBackgroundColor; + bool m_plotDrawingSheet; +}; + +#endif \ No newline at end of file diff --git a/common/jobs/job_export_sch_svg.h b/common/jobs/job_export_sch_svg.h new file mode 100644 index 0000000000..c5416ae7dd --- /dev/null +++ b/common/jobs/job_export_sch_svg.h @@ -0,0 +1,46 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright (C) 1992-2022 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_SCH_SVG_H +#define JOB_EXPORT_SCH_SVG_H + +#include +#include "job.h" + +class JOB_EXPORT_SCH_SVG : public JOB +{ +public: + JOB_EXPORT_SCH_SVG( bool aIsCli ) : + JOB( "svg", aIsCli ), + m_filename(), + m_outputDirectory() + { + } + + wxString m_filename; + wxString m_outputDirectory; + wxString m_colorTheme; + + bool m_blackAndWhite; + bool m_useBackgroundColor; + bool m_plotDrawingSheet; +}; + +#endif \ No newline at end of file diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 7bd1aeea11..3bd5ef0f13 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -190,6 +190,8 @@ set( EESCHEMA_SRCS cross-probing.cpp ee_collectors.cpp eeschema_config.cpp + eeschema_helpers.cpp + eeschema_jobs_handler.cpp eeschema_settings.cpp erc.cpp erc_item.cpp @@ -228,6 +230,7 @@ set( EESCHEMA_SRCS sch_no_connect.cpp sch_painter.cpp sch_pin.cpp + sch_plotter.cpp sch_plugin.cpp sch_preview_panel.cpp sch_screen.cpp @@ -305,7 +308,7 @@ set( EESCHEMA_SRCS sim/kibis/ibis_parser.cpp sim/kibis/kibis.cpp - + tools/assign_footprints.cpp tools/backannotate.cpp tools/ee_actions.cpp diff --git a/eeschema/dialogs/dialog_plot_schematic.cpp b/eeschema/dialogs/dialog_plot_schematic.cpp index 3fae1eda63..e8ecd0d320 100644 --- a/eeschema/dialogs/dialog_plot_schematic.cpp +++ b/eeschema/dialogs/dialog_plot_schematic.cpp @@ -53,44 +53,7 @@ // static members (static to remember last state): int DIALOG_PLOT_SCHEMATIC::m_pageSizeSelect = PAGE_SIZE_AUTO; -int DIALOG_PLOT_SCHEMATIC::m_HPGLPaperSizeSelect = PAGE_SIZE_AUTO; - - -enum HPGL_PAGEZ_T { - PAGE_DEFAULT = 0, - HPGL_PAGE_SIZE_A5, - HPGL_PAGE_SIZE_A4, - HPGL_PAGE_SIZE_A3, - HPGL_PAGE_SIZE_A2, - HPGL_PAGE_SIZE_A1, - HPGL_PAGE_SIZE_A0, - HPGL_PAGE_SIZE_A, - HPGL_PAGE_SIZE_B, - HPGL_PAGE_SIZE_C, - HPGL_PAGE_SIZE_D, - HPGL_PAGE_SIZE_E, -}; - - -static const wxChar* plot_sheet_list( int aSize ) -{ - switch( aSize ) - { - default: - case PAGE_DEFAULT: return nullptr; - case HPGL_PAGE_SIZE_A5: return wxT( "A5" ); - case HPGL_PAGE_SIZE_A4: return wxT( "A4" ); - case HPGL_PAGE_SIZE_A3: return wxT( "A3" ); - case HPGL_PAGE_SIZE_A2: return wxT( "A2" ); - case HPGL_PAGE_SIZE_A1: return wxT( "A1" ); - case HPGL_PAGE_SIZE_A0: return wxT( "A0" ); - case HPGL_PAGE_SIZE_A: return wxT( "A" ); - case HPGL_PAGE_SIZE_B: return wxT( "B" ); - case HPGL_PAGE_SIZE_C: return wxT( "C" ); - case HPGL_PAGE_SIZE_D: return wxT( "D" ); - case HPGL_PAGE_SIZE_E: return wxT( "E" ); - } -} +HPGL_PAGE_SIZE DIALOG_PLOT_SCHEMATIC::m_HPGLPaperSizeSelect = HPGL_PAGE_SIZE::DEFAULT; DIALOG_PLOT_SCHEMATIC::DIALOG_PLOT_SCHEMATIC( SCH_EDIT_FRAME* parent ) @@ -149,7 +112,7 @@ void DIALOG_PLOT_SCHEMATIC::initDlg() // HPGL plot origin and unit system configuration m_plotOriginOpt->SetSelection( cfg->m_PlotPanel.hpgl_origin ); - m_HPGLPaperSizeSelect = cfg->m_PlotPanel.hpgl_paper_size; + m_HPGLPaperSizeSelect = static_cast( cfg->m_PlotPanel.hpgl_paper_size ); // HPGL Pen Size is stored in mm in config m_HPGLPenSize = cfg->m_PlotPanel.hpgl_pen_size * schIUScale.IU_PER_MM; @@ -258,7 +221,7 @@ PLOT_FORMAT DIALOG_PLOT_SCHEMATIC::GetPlotFileFormat() void DIALOG_PLOT_SCHEMATIC::OnPageSizeSelected( wxCommandEvent& event ) { if( GetPlotFileFormat() == PLOT_FORMAT::HPGL ) - m_HPGLPaperSizeSelect = m_paperSizeOption->GetSelection(); + m_HPGLPaperSizeSelect = static_cast( m_paperSizeOption->GetSelection() ); else m_pageSizeSelect = m_paperSizeOption->GetSelection(); } @@ -291,7 +254,7 @@ void DIALOG_PLOT_SCHEMATIC::OnUpdateUI( wxUpdateUIEvent& event ) paperSizes.push_back( _( "D" ) ); paperSizes.push_back( _( "E" ) ); - selection = m_HPGLPaperSizeSelect; + selection = static_cast( m_HPGLPaperSizeSelect ); } else { @@ -339,7 +302,7 @@ void DIALOG_PLOT_SCHEMATIC::getPlotOptions( RENDER_SETTINGS* aSettings ) cfg->m_PlotPanel.frame_reference = getPlotDrawingSheet(); cfg->m_PlotPanel.format = static_cast( GetPlotFileFormat() ); cfg->m_PlotPanel.hpgl_origin = m_plotOriginOpt->GetSelection(); - cfg->m_PlotPanel.hpgl_paper_size = m_HPGLPaperSizeSelect; + cfg->m_PlotPanel.hpgl_paper_size = static_cast( m_HPGLPaperSizeSelect ); cfg->m_PlotPanel.open_file_after_plot = getOpenFileAfterPlot(); // HPGL Pen Size is stored in mm in config @@ -398,202 +361,29 @@ void DIALOG_PLOT_SCHEMATIC::plotSchematic( bool aPlotAll ) getPlotOptions( &renderSettings ); - switch( GetPlotFileFormat() ) - { - default: - case PLOT_FORMAT::POST: - createPSFiles( aPlotAll, getPlotDrawingSheet(), &renderSettings ); - break; - case PLOT_FORMAT::DXF: - createDXFFiles( aPlotAll, getPlotDrawingSheet(), &renderSettings ); - break; - case PLOT_FORMAT::PDF: - createPDFFile( aPlotAll, getPlotDrawingSheet(), &renderSettings ); - break; - case PLOT_FORMAT::SVG: - createSVGFiles( aPlotAll, getPlotDrawingSheet(), &renderSettings ); - break; - case PLOT_FORMAT::HPGL: - createHPGLFiles( aPlotAll, getPlotDrawingSheet(), &renderSettings ); - break; - } -} - - -wxFileName DIALOG_PLOT_SCHEMATIC::createPlotFileName( const wxString& aPlotFileName, - const wxString& aExtension, - REPORTER* aReporter ) -{ - wxFileName retv; - wxFileName tmp; - - tmp.SetPath( getOutputPath() ); - retv.SetPath( tmp.GetPath() ); - - if( !aPlotFileName.IsEmpty() ) - retv.SetName( aPlotFileName ); - else - retv.SetName( _( "Schematic" ) ); - - retv.SetExt( aExtension ); - - if( !EnsureFileDirectoryExists( &tmp, retv.GetFullName(), aReporter ) || !tmp.IsDirWritable() ) - { - wxString msg = wxString::Format( _( "Failed to write plot files to folder '%s'." ), - tmp.GetPath() ); - aReporter->Report( msg, RPT_SEVERITY_ERROR ); - retv.Clear(); - - SCHEMATIC_SETTINGS& settings = m_parent->Schematic().Settings(); - settings.m_PlotDirectoryName.Clear(); - - m_configChanged = true; - } - else - { - retv.SetPath( tmp.GetPath() ); - } - - wxLogTrace( tracePathsAndFiles, "Writing plot file '%s'.", retv.GetFullPath() ); - - return retv; -} - - -void DIALOG_PLOT_SCHEMATIC::createDXFFiles( bool aPlotAll, bool aPlotDrawingSheet, - RENDER_SETTINGS* aRenderSettings ) -{ - SCH_EDIT_FRAME* schframe = m_parent; - SCH_SHEET_PATH oldsheetpath = schframe->GetCurrentSheet(); - - /* When printing all pages, the printed page is not the current page. In complex hierarchies, - * we must update symbol references and other parameters in the given printed SCH_SCREEN, - * according to the sheet path because in complex hierarchies a SCH_SCREEN (a drawing ) is - * shared between many sheets and symbol references depend on the actual sheet path used. - */ - SCH_SHEET_LIST sheetList; - - if( aPlotAll ) - { - sheetList.BuildSheetList( &schframe->Schematic().Root(), true ); - sheetList.SortByPageNumbers(); - } - else - { - sheetList.push_back( schframe->GetCurrentSheet() ); - } - - REPORTER& reporter = m_MessagesBox->Reporter(); - - for( unsigned i = 0; i < sheetList.size(); i++ ) - { - schframe->SetCurrentSheet( sheetList[i] ); - schframe->GetCurrentSheet().UpdateAllScreenReferences(); - schframe->SetSheetNumberAndCount(); - - SCH_SCREEN* screen = schframe->GetCurrentSheet().LastScreen(); - wxPoint plot_offset; - wxString msg; - - try - { - wxString fname = schframe->GetUniqueFilenameForCurrentSheet(); - - // The sub sheet can be in a sub_hierarchy, but we plot the file in the - // main project folder (or the folder specified by the caller), - // so replace separators to create a unique filename: - fname.Replace( "/", "_" ); - fname.Replace( "\\", "_" ); - wxString ext = DXF_PLOTTER::GetDefaultFileExtension(); - wxFileName plotFileName = createPlotFileName( fname, ext, &reporter ); - - if( !plotFileName.IsOk() ) - return; - - if( plotOneSheetDXF( plotFileName.GetFullPath(), screen, aRenderSettings, - plot_offset, 1.0, aPlotDrawingSheet ) ) - { - msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() ); - reporter.Report( msg, RPT_SEVERITY_ACTION ); - } - else // Error - { - msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() ); - reporter.Report( msg, RPT_SEVERITY_ERROR ); - } - } - catch( IO_ERROR& e ) - { - msg.Printf( wxT( "DXF Plotter exception: %s"), e.What() ); - reporter.Report( msg, RPT_SEVERITY_ERROR ); - schframe->SetCurrentSheet( oldsheetpath ); - schframe->GetCurrentSheet().UpdateAllScreenReferences(); - schframe->SetSheetNumberAndCount(); - return; - } - } - - reporter.ReportTail( _( "Done." ), RPT_SEVERITY_INFO ); - - schframe->SetCurrentSheet( oldsheetpath ); - schframe->GetCurrentSheet().UpdateAllScreenReferences(); - schframe->SetSheetNumberAndCount(); -} - - -bool DIALOG_PLOT_SCHEMATIC::plotOneSheetDXF( const wxString& aFileName, - SCH_SCREEN* aScreen, - RENDER_SETTINGS* aRenderSettings, - const wxPoint& aPlotOffset, - double aScale, - bool aPlotFrameRef ) -{ - aRenderSettings->LoadColors( getColorSettings() ); - aRenderSettings->SetDefaultPenWidth( 0 ); - - const PAGE_INFO& pageInfo = aScreen->GetPageSettings(); - DXF_PLOTTER* plotter = new DXF_PLOTTER(); + std::unique_ptr schPlotter = std::make_unique( m_parent ); - plotter->SetRenderSettings( aRenderSettings ); - plotter->SetPageSettings( pageInfo ); - plotter->SetColorMode( getModeColor() ); + COLOR_SETTINGS* colors = getColorSettings(); - // Currently, plot units are in decimil - plotter->SetViewport( aPlotOffset, schIUScale.IU_PER_MILS/10, aScale, false ); + SCH_PLOT_SETTINGS plotSettings; + plotSettings.m_plotDrawingSheet = getPlotDrawingSheet(); + plotSettings.m_plotAll = aPlotAll; + plotSettings.m_blackAndWhite = !getModeColor(); + plotSettings.m_useBackgroundColor = m_plotBackgroundColor->GetValue(); + plotSettings.m_theme = colors->GetFilename(); + plotSettings.m_HPGLPenSize = m_HPGLPenSize; + plotSettings.m_HPGLPaperSizeSelect = static_cast( m_HPGLPaperSizeSelect ); + plotSettings.m_HPGLPlotOrigin = + static_cast( m_plotOriginOpt->GetSelection() ); + plotSettings.m_outputDirectory = getOutputPath(); + plotSettings.m_pageSizeSelect = m_pageSizeSelect; - // Init : - plotter->SetCreator( wxT( "Eeschema-DXF" ) ); - if( ! plotter->OpenFile( aFileName ) ) - { - delete plotter; - return false; - } - - LOCALE_IO toggle; + schPlotter->Plot( GetPlotFileFormat(), plotSettings, &renderSettings, + &m_MessagesBox->Reporter() ); - plotter->StartPlot( m_parent->GetCurrentSheet().GetPageNumber() ); - - if( aPlotFrameRef ) - { - wxString sheetName = m_parent->GetCurrentSheet().Last()->GetName(); - wxString sheetPath = m_parent->GetCurrentSheet().PathHumanReadable(); - COLOR4D color = plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_DRAWINGSHEET ); - - PlotDrawingSheet( plotter, &m_parent->Prj(), m_parent->GetTitleBlock(), pageInfo, - aScreen->Schematic()->GetProperties(), aScreen->GetPageNumber(), - aScreen->GetPageCount(), sheetName, sheetPath, aScreen->GetFileName(), - plotter->GetColorMode() ? color : COLOR4D::BLACK, - aScreen->GetVirtualPageNumber() == 1 ); - } - - aScreen->Plot( plotter ); - - // finish - plotter->EndPlot(); - delete plotter; - - return true; + if( GetPlotFileFormat() == PLOT_FORMAT::PDF && getOpenFileAfterPlot() ) + wxLaunchDefaultApplication( schPlotter->GetLastOutputFilePath() ); } @@ -609,661 +399,6 @@ void DIALOG_PLOT_SCHEMATIC::setHpglPenWidth() } -void DIALOG_PLOT_SCHEMATIC::createHPGLFiles( bool aPlotAll, bool aPlotFrameRef, - RENDER_SETTINGS* aRenderSettings ) -{ - SCH_SCREEN* screen = m_parent->GetScreen(); - SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet(); - - /* When printing all pages, the printed page is not the current page. In complex hierarchies, - * we must update symbol references and other parameters in the given printed SCH_SCREEN, - * according to the sheet path because in complex hierarchies a SCH_SCREEN (a drawing ) is - * shared between many sheets and symbol references depend on the actual sheet path used. - */ - SCH_SHEET_LIST sheetList; - - if( aPlotAll ) - { - sheetList.BuildSheetList( &m_parent->Schematic().Root(), true ); - sheetList.SortByPageNumbers(); - } - else - { - sheetList.push_back( m_parent->GetCurrentSheet() ); - } - - REPORTER& reporter = m_MessagesBox->Reporter(); - - setHpglPenWidth(); - - for( unsigned i = 0; i < sheetList.size(); i++ ) - { - m_parent->SetCurrentSheet( sheetList[i] ); - m_parent->GetCurrentSheet().UpdateAllScreenReferences(); - m_parent->SetSheetNumberAndCount(); - - screen = m_parent->GetCurrentSheet().LastScreen(); - - if( !screen ) // LastScreen() may return NULL - screen = m_parent->GetScreen(); - - const PAGE_INFO& curPage = screen->GetPageSettings(); - - PAGE_INFO plotPage = curPage; - - // if plotting on a page size other than curPage - if( m_paperSizeOption->GetSelection() != PAGE_DEFAULT ) - plotPage.SetType( plot_sheet_list( m_paperSizeOption->GetSelection() ) ); - - // Calculation of conversion scales. - double plot_scale = (double) plotPage.GetWidthMils() / curPage.GetWidthMils(); - - // Calculate offsets - wxPoint plotOffset; - wxString msg; - - if( getPlotOriginAndUnits() == HPGL_PLOT_ORIGIN_AND_UNITS::PLOTTER_CENTER ) - { - plotOffset.x = plotPage.GetWidthIU( schIUScale.IU_PER_MILS ) / 2; - plotOffset.y = -plotPage.GetHeightIU( schIUScale.IU_PER_MILS ) / 2; - } - - try - { - wxString fname = m_parent->GetUniqueFilenameForCurrentSheet(); - // The sub sheet can be in a sub_hierarchy, but we plot the file in the - // main project folder (or the folder specified by the caller), - // so replace separators to create a unique filename: - fname.Replace( "/", "_" ); - fname.Replace( "\\", "_" ); - wxString ext = HPGL_PLOTTER::GetDefaultFileExtension(); - wxFileName plotFileName = createPlotFileName( fname, ext, &reporter ); - - if( !plotFileName.IsOk() ) - return; - - LOCALE_IO toggle; - - if( plotOneSheetHpgl( plotFileName.GetFullPath(), screen, plotPage, aRenderSettings, - plotOffset, plot_scale, aPlotFrameRef, getPlotOriginAndUnits() ) ) - { - msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() ); - reporter.Report( msg, RPT_SEVERITY_ACTION ); - } - else - { - msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() ); - reporter.Report( msg, RPT_SEVERITY_ERROR ); - } - } - catch( IO_ERROR& e ) - { - msg.Printf( wxT( "HPGL Plotter exception: %s"), e.What() ); - reporter.Report( msg, RPT_SEVERITY_ERROR ); - } - } - - reporter.ReportTail( _( "Done." ), RPT_SEVERITY_INFO ); - - m_parent->SetCurrentSheet( oldsheetpath ); - m_parent->GetCurrentSheet().UpdateAllScreenReferences(); - m_parent->SetSheetNumberAndCount(); -} - - -bool DIALOG_PLOT_SCHEMATIC::plotOneSheetHpgl( const wxString& aFileName, - SCH_SCREEN* aScreen, - const PAGE_INFO& aPageInfo, - RENDER_SETTINGS* aRenderSettings, - const wxPoint& aPlot0ffset, - double aScale, - bool aPlotFrameRef, - HPGL_PLOT_ORIGIN_AND_UNITS aOriginAndUnits ) -{ - HPGL_PLOTTER* plotter = new HPGL_PLOTTER(); - // Currently, plot units are in decimil - - plotter->SetPageSettings( aPageInfo ); - plotter->SetRenderSettings( aRenderSettings ); - plotter->RenderSettings()->LoadColors( getColorSettings() ); - plotter->SetColorMode( getModeColor() ); - plotter->SetViewport( aPlot0ffset, schIUScale.IU_PER_MILS/10, aScale, false ); - - // TODO this could be configurable - plotter->SetTargetChordLength( schIUScale.mmToIU( 0.6 ) ); - - switch( aOriginAndUnits ) - { - case HPGL_PLOT_ORIGIN_AND_UNITS::PLOTTER_BOT_LEFT: - case HPGL_PLOT_ORIGIN_AND_UNITS::PLOTTER_CENTER: - default: - plotter->SetUserCoords( false ); - break; - case HPGL_PLOT_ORIGIN_AND_UNITS::USER_FIT_PAGE: - plotter->SetUserCoords( true ); - plotter->SetUserCoordsFit( false ); - break; - case HPGL_PLOT_ORIGIN_AND_UNITS::USER_FIT_CONTENT: - plotter->SetUserCoords( true ); - plotter->SetUserCoordsFit( true ); - break; - } - - // Init : - plotter->SetCreator( wxT( "Eeschema-HPGL" ) ); - - if( !plotter->OpenFile( aFileName ) ) - { - delete plotter; - return false; - } - - LOCALE_IO toggle; - - // Pen num and pen speed are not initialized here. - // Default HPGL driver values are used - plotter->SetPenDiameter( m_HPGLPenSize ); - plotter->StartPlot( m_parent->GetCurrentSheet().GetPageNumber() ); - - if( aPlotFrameRef ) - { - wxString sheetName = m_parent->GetCurrentSheet().Last()->GetName(); - wxString sheetPath = m_parent->GetCurrentSheet().PathHumanReadable(); - - PlotDrawingSheet( plotter, &m_parent->Prj(), m_parent->GetTitleBlock(), aPageInfo, - aScreen->Schematic()->GetProperties(), aScreen->GetPageNumber(), - aScreen->GetPageCount(), sheetName, sheetPath, aScreen->GetFileName(), - COLOR4D::BLACK, aScreen->GetVirtualPageNumber() == 1 ); - } - - aScreen->Plot( plotter ); - - plotter->EndPlot(); - delete plotter; - - return true; -} - - -void DIALOG_PLOT_SCHEMATIC::createPDFFile( bool aPlotAll, bool aPlotDrawingSheet, - RENDER_SETTINGS* aRenderSettings ) -{ - SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet(); // sheetpath is saved here - - /* When printing all pages, the printed page is not the current page. In complex hierarchies, - * we must update symbol references and other parameters in the given printed SCH_SCREEN, - * according to the sheet path because in complex hierarchies a SCH_SCREEN (a drawing ) is - * shared between many sheets and symbol references depend on the actual sheet path used. - */ - SCH_SHEET_LIST sheetList; - - if( aPlotAll ) - { - sheetList.BuildSheetList( &m_parent->Schematic().Root(), true ); - sheetList.SortByPageNumbers(); - } - else - { - sheetList.push_back( m_parent->GetCurrentSheet() ); - } - - // Allocate the plotter and set the job level parameter - PDF_PLOTTER* plotter = new PDF_PLOTTER(); - plotter->SetRenderSettings( aRenderSettings ); - plotter->SetColorMode( getModeColor() ); - plotter->SetCreator( wxT( "Eeschema-PDF" ) ); - plotter->SetTitle( ExpandTextVars( m_parent->GetTitleBlock().GetTitle(), &m_parent->Prj() ) ); - - wxString msg; - wxFileName plotFileName; - REPORTER& reporter = m_MessagesBox->Reporter(); - LOCALE_IO toggle; // Switch the locale to standard C - - for( unsigned i = 0; i < sheetList.size(); i++ ) - { - m_parent->SetCurrentSheet( sheetList[i] ); - m_parent->GetCurrentSheet().UpdateAllScreenReferences(); - m_parent->SetSheetNumberAndCount(); - SCH_SCREEN* screen = m_parent->GetCurrentSheet().LastScreen(); - - if( i == 0 ) - { - try - { - wxString fname = m_parent->GetUniqueFilenameForCurrentSheet(); - - // The sub sheet can be in a sub_hierarchy, but we plot the file in the main - // project folder (or the folder specified by the caller), so replace separators - // to create a unique filename: - fname.Replace( "/", "_" ); - fname.Replace( "\\", "_" ); - wxString ext = PDF_PLOTTER::GetDefaultFileExtension(); - plotFileName = createPlotFileName( fname, ext, &reporter ); - - if( !plotFileName.IsOk() ) - return; - - if( !plotter->OpenFile( plotFileName.GetFullPath() ) ) - { - msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() ); - reporter.Report( msg, RPT_SEVERITY_ERROR ); - delete plotter; - return; - } - - // Open the plotter and do the first page - setupPlotPagePDF( plotter, screen ); - plotter->StartPlot( sheetList[i].GetPageNumber(), _("Root") ); - } - catch( const IO_ERROR& e ) - { - // Cannot plot PDF file - msg.Printf( wxT( "PDF Plotter exception: %s" ), e.What() ); - reporter.Report( msg, RPT_SEVERITY_ERROR ); - - restoreEnvironment( plotter, oldsheetpath ); - return; - } - - } - else - { - /* For the following pages you need to close the (finished) page, - * reconfigure, and then start a new one */ - plotter->ClosePage(); - setupPlotPagePDF( plotter, screen ); - plotter->StartPage( sheetList[i].GetPageNumber(), - sheetList[i].Last()->GetFields()[SHEETNAME].GetShownText() ); - } - - plotOneSheetPDF( plotter, screen, aPlotDrawingSheet ); - } - - // Everything done, close the plot and restore the environment - msg.Printf( _( "Plotted to '%s'.\n" ), plotFileName.GetFullPath() ); - reporter.Report( msg, RPT_SEVERITY_ACTION ); - reporter.ReportTail( _( "Done." ), RPT_SEVERITY_INFO ); - - restoreEnvironment( plotter, oldsheetpath ); - - if( getOpenFileAfterPlot()) - wxLaunchDefaultApplication( plotFileName.GetFullPath() ); -} - - -void DIALOG_PLOT_SCHEMATIC::restoreEnvironment( PDF_PLOTTER* aPlotter, - SCH_SHEET_PATH& aOldsheetpath ) -{ - aPlotter->EndPlot(); - delete aPlotter; - - // Restore the previous sheet - m_parent->SetCurrentSheet( aOldsheetpath ); - m_parent->GetCurrentSheet().UpdateAllScreenReferences(); - m_parent->SetSheetNumberAndCount(); -} - - -void DIALOG_PLOT_SCHEMATIC::plotOneSheetPDF( PLOTTER* aPlotter, SCH_SCREEN* aScreen, - bool aPlotDrawingSheet ) -{ - if( m_plotBackgroundColor->GetValue() && aPlotter->GetColorMode() ) - { - aPlotter->SetColor( aPlotter->RenderSettings()->GetBackgroundColor() ); - wxPoint end( aPlotter->PageSettings().GetWidthIU( schIUScale.IU_PER_MILS ), - aPlotter->PageSettings().GetHeightIU( schIUScale.IU_PER_MILS ) ); - aPlotter->Rect( wxPoint( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 ); - } - - if( aPlotDrawingSheet ) - { - COLOR4D color = COLOR4D::BLACK; - - if( aPlotter->GetColorMode() ) - color = aPlotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_DRAWINGSHEET ); - - wxString sheetName = m_parent->GetCurrentSheet().Last()->GetName(); - wxString sheetPath = m_parent->GetCurrentSheet().PathHumanReadable(); - - PlotDrawingSheet( aPlotter, &aScreen->Schematic()->Prj(), m_parent->GetTitleBlock(), - m_parent->GetPageSettings(), aScreen->Schematic()->GetProperties(), - aScreen->GetPageNumber(), aScreen->GetPageCount(), sheetName, sheetPath, - aScreen->GetFileName(), color, aScreen->GetVirtualPageNumber() == 1 ); - } - - aScreen->Plot( aPlotter ); -} - - -void DIALOG_PLOT_SCHEMATIC::setupPlotPagePDF( PLOTTER* aPlotter, SCH_SCREEN* aScreen ) -{ - PAGE_INFO plotPage; // page size selected to plot - - // Considerations on page size and scaling requests - const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic - - switch( m_pageSizeSelect ) - { - case PAGE_SIZE_A: - plotPage.SetType( wxT( "A" ) ); - plotPage.SetPortrait( actualPage.IsPortrait() ); - break; - - case PAGE_SIZE_A4: - plotPage.SetType( wxT( "A4" ) ); - plotPage.SetPortrait( actualPage.IsPortrait() ); - break; - - case PAGE_SIZE_AUTO: - default: - plotPage = actualPage; - break; - } - - double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils(); - double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils(); - double scale = std::min( scalex, scaley ); - aPlotter->SetPageSettings( plotPage ); - - // Currently, plot units are in decimil - aPlotter->SetViewport( wxPoint( 0, 0 ), schIUScale.IU_PER_MILS/10, scale, false ); -} - - -void DIALOG_PLOT_SCHEMATIC::createPSFiles( bool aPlotAll, bool aPlotFrameRef, - RENDER_SETTINGS* aRenderSettings ) -{ - SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet(); // sheetpath is saved here - PAGE_INFO plotPage; // page size selected to plot - wxString msg; - REPORTER& reporter = m_MessagesBox->Reporter(); - - /* When printing all pages, the printed page is not the current page. - * In complex hierarchies, we must update symbol references and other parameters in the - * given printed SCH_SCREEN, accordant to the sheet path because in complex hierarchies - * a SCH_SCREEN (a drawing ) is shared between many sheets and symbol references - * depend on the actual sheet path used. - */ - SCH_SHEET_LIST sheetList; - - if( aPlotAll ) - { - sheetList.BuildSheetList( &m_parent->Schematic().Root(), true ); - sheetList.SortByPageNumbers(); - } - else - { - sheetList.push_back( m_parent->GetCurrentSheet() ); - } - - for( unsigned i = 0; i < sheetList.size(); i++ ) - { - m_parent->SetCurrentSheet( sheetList[i] ); - m_parent->GetCurrentSheet().UpdateAllScreenReferences(); - m_parent->SetSheetNumberAndCount(); - - SCH_SCREEN* screen = m_parent->GetCurrentSheet().LastScreen(); - PAGE_INFO actualPage = screen->GetPageSettings(); - - switch( m_pageSizeSelect ) - { - case PAGE_SIZE_A: - plotPage.SetType( wxT( "A" ) ); - plotPage.SetPortrait( actualPage.IsPortrait() ); - break; - - case PAGE_SIZE_A4: - plotPage.SetType( wxT( "A4" ) ); - plotPage.SetPortrait( actualPage.IsPortrait() ); - break; - - case PAGE_SIZE_AUTO: - default: - plotPage = actualPage; - break; - } - - double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils(); - double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils(); - double scale = std::min( scalex, scaley ); - wxPoint plot_offset; - - try - { - wxString fname = m_parent->GetUniqueFilenameForCurrentSheet(); - - // The sub sheet can be in a sub_hierarchy, but we plot the file in the - // main project folder (or the folder specified by the caller), - // so replace separators to create a unique filename: - fname.Replace( "/", "_" ); - fname.Replace ("\\", "_" ); - wxString ext = PS_PLOTTER::GetDefaultFileExtension(); - wxFileName plotFileName = createPlotFileName( fname, ext, &reporter ); - - if( !plotFileName.IsOk() ) - return; - - if( plotOneSheetPS( plotFileName.GetFullPath(), screen, aRenderSettings, plotPage, - plot_offset, scale, aPlotFrameRef ) ) - { - msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() ); - reporter.Report( msg, RPT_SEVERITY_ACTION ); - } - else - { - // Error - msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() ); - reporter.Report( msg, RPT_SEVERITY_ERROR ); - } - - } - catch( IO_ERROR& e ) - { - msg.Printf( wxT( "PS Plotter exception: %s"), e.What() ); - reporter.Report( msg, RPT_SEVERITY_ERROR ); - } - } - - reporter.ReportTail( _( "Done." ), RPT_SEVERITY_INFO ); - - m_parent->SetCurrentSheet( oldsheetpath ); - m_parent->GetCurrentSheet().UpdateAllScreenReferences(); - m_parent->SetSheetNumberAndCount(); -} - - -bool DIALOG_PLOT_SCHEMATIC::plotOneSheetPS( const wxString& aFileName, - SCH_SCREEN* aScreen, - RENDER_SETTINGS* aRenderSettings, - const PAGE_INFO& aPageInfo, - const wxPoint& aPlot0ffset, - double aScale, - bool aPlotFrameRef ) -{ - PS_PLOTTER* plotter = new PS_PLOTTER(); - plotter->SetRenderSettings( aRenderSettings ); - plotter->SetPageSettings( aPageInfo ); - plotter->SetColorMode( getModeColor() ); - - // Currently, plot units are in decimil - plotter->SetViewport( aPlot0ffset, schIUScale.IU_PER_MILS/10, aScale, false ); - - // Init : - plotter->SetCreator( wxT( "Eeschema-PS" ) ); - - if( ! plotter->OpenFile( aFileName ) ) - { - delete plotter; - return false; - } - - LOCALE_IO toggle; // Switch the locale to standard C - - plotter->StartPlot( m_parent->GetCurrentSheet().GetPageNumber() ); - - if( m_plotBackgroundColor->GetValue() && plotter->GetColorMode() ) - { - plotter->SetColor( plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) ); - wxPoint end( plotter->PageSettings().GetWidthIU( schIUScale.IU_PER_MILS ), - plotter->PageSettings().GetHeightIU( schIUScale.IU_PER_MILS ) ); - plotter->Rect( wxPoint( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 ); - } - - if( aPlotFrameRef ) - { - wxString sheetName = m_parent->GetCurrentSheet().Last()->GetName(); - wxString sheetPath = m_parent->GetCurrentSheet().PathHumanReadable(); - COLOR4D color = plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_DRAWINGSHEET ); - - PlotDrawingSheet( plotter, &aScreen->Schematic()->Prj(), m_parent->GetTitleBlock(), - aPageInfo, aScreen->Schematic()->GetProperties(), aScreen->GetPageNumber(), - aScreen->GetPageCount(), sheetName, sheetPath, aScreen->GetFileName(), - plotter->GetColorMode() ? color : COLOR4D::BLACK, - aScreen->GetVirtualPageNumber() == 1 ); - } - - aScreen->Plot( plotter ); - - plotter->EndPlot(); - delete plotter; - - return true; -} - - -void DIALOG_PLOT_SCHEMATIC::createSVGFiles( bool aPrintAll, bool aPrintFrameRef, - RENDER_SETTINGS* aRenderSettings ) -{ - wxString msg; - REPORTER& reporter = m_MessagesBox->Reporter(); - SCH_SHEET_PATH oldsheetpath = m_parent->GetCurrentSheet(); - SCH_SHEET_LIST sheetList; - - if( aPrintAll ) - { - sheetList.BuildSheetList( &m_parent->Schematic().Root(), true ); - sheetList.SortByPageNumbers(); - } - else - { - sheetList.push_back( m_parent->GetCurrentSheet() ); - } - - for( unsigned i = 0; i < sheetList.size(); i++ ) - { - SCH_SCREEN* screen; - m_parent->SetCurrentSheet( sheetList[i] ); - m_parent->GetCurrentSheet().UpdateAllScreenReferences(); - m_parent->SetSheetNumberAndCount(); - screen = m_parent->GetCurrentSheet().LastScreen(); - - try - { - wxString fname = m_parent->GetUniqueFilenameForCurrentSheet(); - - // The sub sheet can be in a sub_hierarchy, but we plot the file in the - // main project folder (or the folder specified by the caller), - // so replace separators to create a unique filename: - fname.Replace( "/", "_" ); - fname.Replace( "\\", "_" ); - wxString ext = SVG_PLOTTER::GetDefaultFileExtension(); - wxFileName plotFileName = createPlotFileName( fname, ext, &reporter ); - - if( !plotFileName.IsOk() ) - return; - - bool success = plotOneSheetSVG( plotFileName.GetFullPath(), screen, aRenderSettings, - getModeColor() ? false : true, aPrintFrameRef ); - - if( !success ) - { - msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() ); - reporter.Report( msg, RPT_SEVERITY_ERROR ); - } - else - { - msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() ); - reporter.Report( msg, RPT_SEVERITY_ACTION ); - } - } - catch( const IO_ERROR& e ) - { - // Cannot plot SVG file - msg.Printf( wxT( "SVG Plotter exception: %s" ), e.What() ); - reporter.Report( msg, RPT_SEVERITY_ERROR ); - break; - } - } - - reporter.ReportTail( _( "Done" ), RPT_SEVERITY_INFO ); - - m_parent->SetCurrentSheet( oldsheetpath ); - m_parent->GetCurrentSheet().UpdateAllScreenReferences(); - m_parent->SetSheetNumberAndCount(); -} - - -bool DIALOG_PLOT_SCHEMATIC::plotOneSheetSVG( const wxString& aFileName, - SCH_SCREEN* aScreen, - RENDER_SETTINGS* aRenderSettings, - bool aPlotBlackAndWhite, - bool aPlotFrameRef ) -{ - const PAGE_INFO& pageInfo = aScreen->GetPageSettings(); - - SVG_PLOTTER* plotter = new SVG_PLOTTER(); - plotter->SetRenderSettings( aRenderSettings ); - plotter->SetPageSettings( pageInfo ); - plotter->SetColorMode( aPlotBlackAndWhite ? false : true ); - wxPoint plot_offset; - double scale = 1.0; - - // Currently, plot units are in decimil - plotter->SetViewport( plot_offset, schIUScale.IU_PER_MILS/10, scale, false ); - - // Init : - plotter->SetCreator( wxT( "Eeschema-SVG" ) ); - - if( ! plotter->OpenFile( aFileName ) ) - { - delete plotter; - return false; - } - - LOCALE_IO toggle; - - plotter->StartPlot( m_parent->GetCurrentSheet().GetPageNumber() ); - - if( m_plotBackgroundColor->GetValue() && plotter->GetColorMode() ) - { - plotter->SetColor( plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) ); - wxPoint end( plotter->PageSettings().GetWidthIU( schIUScale.IU_PER_MILS ), - plotter->PageSettings().GetHeightIU( schIUScale.IU_PER_MILS ) ); - plotter->Rect( wxPoint( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 ); - } - - if( aPlotFrameRef ) - { - wxString sheetName = m_parent->GetCurrentSheet().Last()->GetName(); - wxString sheetPath = m_parent->GetCurrentSheet().PathHumanReadable(); - COLOR4D color = plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_DRAWINGSHEET ); - - PlotDrawingSheet( plotter, &aScreen->Schematic()->Prj(), m_parent->GetTitleBlock(), - pageInfo, aScreen->Schematic()->GetProperties(), aScreen->GetPageNumber(), - aScreen->GetPageCount(), sheetName, sheetPath, aScreen->GetFileName(), - plotter->GetColorMode() ? color : COLOR4D::BLACK, - aScreen->GetVirtualPageNumber() == 1 ); - } - - aScreen->Plot( plotter ); - - plotter->EndPlot(); - delete plotter; - - return true; -} - - wxString DIALOG_PLOT_SCHEMATIC::getOutputPath() { wxString msg; diff --git a/eeschema/dialogs/dialog_plot_schematic.h b/eeschema/dialogs/dialog_plot_schematic.h index 48eac5e11f..822041f8a9 100644 --- a/eeschema/dialogs/dialog_plot_schematic.h +++ b/eeschema/dialogs/dialog_plot_schematic.h @@ -34,21 +34,7 @@ #include #include #include - -enum PageFormatReq -{ - PAGE_SIZE_AUTO, - PAGE_SIZE_A4, - PAGE_SIZE_A -}; - -enum class HPGL_PLOT_ORIGIN_AND_UNITS -{ - PLOTTER_BOT_LEFT, - PLOTTER_CENTER, - USER_FIT_PAGE, - USER_FIT_CONTENT, -}; +#include class PDF_PLOTTER; class SCH_REPORTER; @@ -97,26 +83,9 @@ private: bool getOpenFileAfterPlot() { return m_openFileAfterPlot->GetValue(); } void setOpenFileAfterPlot( bool aOpenFileAfterPlot ) { m_openFileAfterPlot->SetValue( aOpenFileAfterPlot ); } - void plotSchematic( bool aPlotAll ); - - // PDF - void createPDFFile( bool aPlotAll, bool aPlotDrawingSheet, RENDER_SETTINGS* aRenderSettings ); - void plotOneSheetPDF( PLOTTER* aPlotter, SCH_SCREEN* aScreen, bool aPlotDrawingSheet); - void setupPlotPagePDF( PLOTTER* aPlotter, SCH_SCREEN* aScreen ); - - /** - * Everything done, close the plot and restore the environment. - * - * @param aPlotter the plotter to close and destroy - * @param aOldsheetpath the stored old sheet path for the current sheet before the plot started - */ - void restoreEnvironment( PDF_PLOTTER* aPlotter, SCH_SHEET_PATH& aOldsheetpath ); + void setHpglPenWidth(); - // DXF - void createDXFFiles( bool aPlotAll, bool aPlotDrawingSheet, RENDER_SETTINGS* aRenderSettings ); - bool plotOneSheetDXF( const wxString& aFileName, SCH_SCREEN* aScreen, - RENDER_SETTINGS* aRenderSettings, const wxPoint& aPlotOffset, - double aScale, bool aPlotFrameRef ); + void plotSchematic( bool aPlotAll ); // HPGLGetPlotOriginAndUnits HPGL_PLOT_ORIGIN_AND_UNITS getPlotOriginAndUnits() @@ -154,36 +123,6 @@ private: } } - void createHPGLFiles( bool aPlotAll, bool aPlotFrameRef, RENDER_SETTINGS* aRenderSettings ); - void setHpglPenWidth(); - bool plotOneSheetHpgl( const wxString& aFileName, SCH_SCREEN* aScreen, - const PAGE_INFO& aPageInfo, RENDER_SETTINGS* aRenderSettings, - const wxPoint& aPlot0ffset, double aScale, bool aPlotFrameRef, - HPGL_PLOT_ORIGIN_AND_UNITS aOriginAndUnits ); - - // PS - void createPSFiles( bool aPlotAll, bool aPlotFrameRef, RENDER_SETTINGS* aSettings ); - bool plotOneSheetPS( const wxString& aFileName, SCH_SCREEN* aScreen, - RENDER_SETTINGS* aRenderSettings, const PAGE_INFO& aPageInfo, - const wxPoint& aPlot0ffset, double aScale, bool aPlotFrameRef ); - - // SVG - void createSVGFiles( bool aPrintAll, bool aPrintFrameRef, RENDER_SETTINGS* aRenderSettings ); - bool plotOneSheetSVG( const wxString& aFileName, SCH_SCREEN* aScreen, - RENDER_SETTINGS* aRenderSettings, bool aPlotBlackAndWhite, - bool aPlotFrameRef ); - - /** - * Create a file name with an absolute path name. - * - * @param aPlotFileName the name for the file to plot without a path. - * @param aExtension the extension for the file to plot. - * @param aReporter a point to a REPORTER object use to show messages (can be NULL). - * @return the created file name. - * @throw IO_ERROR on file I/O errors. - */ - wxFileName createPlotFileName( const wxString& aPlotFileName, const wxString& aExtension, - REPORTER* aReporter = nullptr ); /** * Determine the best absolute path to plot files given the contents of the path @@ -207,9 +146,8 @@ private: bool m_configChanged; // true if a project config param has changed PLOT_FORMAT m_plotFormat; static int m_pageSizeSelect; // Static to keep last option for some format - static int m_HPGLPaperSizeSelect; // for HPGL format only: last selected paper size - double m_HPGLPenSize; // for HPGL format only: pen size - + static HPGL_PAGE_SIZE m_HPGLPaperSizeSelect; // for HPGL format only: last selected paper size + double m_HPGLPenSize; UNIT_BINDER m_defaultLineWidth; UNIT_BINDER m_penWidth; }; diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp index e9b30313eb..daf97503c3 100644 --- a/eeschema/eeschema.cpp +++ b/eeschema/eeschema.cpp @@ -28,6 +28,8 @@ #include #include #include +#include "eeschema_jobs_handler.h" +#include "eeschema_helpers.h" #include #include #include @@ -142,6 +144,8 @@ static struct IFACE : public KIFACE_BASE { SCH_EDIT_FRAME* frame = new SCH_EDIT_FRAME( aKiway, aParent ); + EESCHEMA_HELPERS::SetSchEditFrame( frame ); + if( Kiface().IsSingle() ) { // only run this under single_top, not under a project manager. @@ -301,6 +305,9 @@ static struct IFACE : public KIFACE_BASE int HandleJob( JOB* aJob ) override; +private: + std::unique_ptr m_jobHandler; + } kiface( "eeschema", KIWAY::FACE_SCH ); } // namespace @@ -377,6 +384,8 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) } } + m_jobHandler = std::make_unique(); + return true; } @@ -565,5 +574,5 @@ void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aProje int IFACE::HandleJob( JOB* aJob ) { - return 0; + return m_jobHandler->RunJob( aJob ); } \ No newline at end of file diff --git a/eeschema/eeschema_helpers.cpp b/eeschema/eeschema_helpers.cpp new file mode 100644 index 0000000000..12f95294cc --- /dev/null +++ b/eeschema/eeschema_helpers.cpp @@ -0,0 +1,154 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 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, you may find one here: + * http://www.gnu.org/licenses/gpl-3.0.html + * or you may search the http://www.gnu.org website for the version 3 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +SCH_EDIT_FRAME* EESCHEMA_HELPERS::s_SchEditFrame = nullptr; +SETTINGS_MANAGER* EESCHEMA_HELPERS::s_SettingsManager = nullptr; + + +void EESCHEMA_HELPERS::SetSchEditFrame( SCH_EDIT_FRAME* aSchEditFrame ) +{ + s_SchEditFrame = aSchEditFrame; +} + + +SETTINGS_MANAGER* EESCHEMA_HELPERS::GetSettingsManager() +{ + if( !s_SettingsManager ) + { + if( s_SchEditFrame ) + { + s_SettingsManager = s_SchEditFrame->GetSettingsManager(); + } + else + { + s_SettingsManager = new SETTINGS_MANAGER( true ); + } + } + + return s_SettingsManager; +} + + +PROJECT* EESCHEMA_HELPERS::GetDefaultProject() +{ + // For some reasons, LoadProject() needs a C locale, so ensure we have the right locale + // This is mainly when running QA Python tests + LOCALE_IO dummy; + + PROJECT* project = GetSettingsManager()->GetProject( "" ); + + if( !project ) + { + GetSettingsManager()->LoadProject( "" ); + project = GetSettingsManager()->GetProject( "" ); + } + + return project; +} + + +SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( wxString& aFileName ) +{ + if( aFileName.EndsWith( KiCadSchematicFileExtension ) ) + return LoadSchematic( aFileName, SCH_IO_MGR::SCH_KICAD ); + else if( aFileName.EndsWith( LegacySchematicFileExtension ) ) + return LoadSchematic( aFileName, SCH_IO_MGR::SCH_LEGACY ); + + // as fall back for any other kind use the legacy format + return LoadSchematic( aFileName, SCH_IO_MGR::SCH_LEGACY ); +} + + +SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( wxString& aFileName, SCH_IO_MGR::SCH_FILE_T aFormat ) +{ + wxFileName pro = aFileName; + pro.SetExt( ProjectFileExtension ); + pro.MakeAbsolute(); + wxString projectPath = pro.GetFullPath(); + + // Ensure the "C" locale is temporary set, before reading any file + // It also avoid wxWidget alerts about locale issues, later, when using Python 3 + LOCALE_IO dummy; + + PROJECT* project = GetSettingsManager()->GetProject( projectPath ); + + if( !project ) + { + if( wxFileExists( projectPath ) ) + { + GetSettingsManager()->LoadProject( projectPath, false ); + project = GetSettingsManager()->GetProject( projectPath ); + } + } + else if( s_SchEditFrame && project == &GetSettingsManager()->Prj() ) + { + // Project is already loaded? Then so is the board + return &s_SchEditFrame->Schematic(); + } + + // Board cannot be loaded without a project, so create the default project + if( !project ) + project = GetDefaultProject(); + + SCH_PLUGIN* plugin = SCH_IO_MGR::FindPlugin( aFormat ); + SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( plugin ); + + SCHEMATIC* schematic = new SCHEMATIC( project ); + + try + { + schematic->SetRoot( pi->Load( aFileName, schematic ) ); + } + catch( ... ) + { + return nullptr; + } + + SCH_SHEET_LIST sheetList = schematic->GetSheets(); + SCH_SCREENS schematicScreenRoot( schematic->Root() ); + + for( SCH_SCREEN* screen = schematicScreenRoot.GetFirst(); screen; + screen = schematicScreenRoot.GetNext() ) + screen->UpdateLocalLibSymbolLinks(); + + if( schematic->RootScreen()->GetFileFormatVersionAtLoad() < 20221002 ) + sheetList.UpdateSymbolInstances( schematic->RootScreen()->GetSymbolInstances() ); + + sheetList.UpdateSheetInstances( schematic->RootScreen()->GetSheetInstances() ); + + schematic->ConnectionGraph()->Reset(); + + schematic->CurrentSheet().LastScreen()->TestDanglingEnds( nullptr, nullptr ); + + return schematic; +} \ No newline at end of file diff --git a/eeschema/eeschema_helpers.h b/eeschema/eeschema_helpers.h new file mode 100644 index 0000000000..e0288eed43 --- /dev/null +++ b/eeschema/eeschema_helpers.h @@ -0,0 +1,56 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 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, you may find one here: + * http://www.gnu.org/licenses/gpl-3.0.html + * or you may search the http://www.gnu.org website for the version 3 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef EESCHEMA_HELPERS_H_ +#define EESCHEMA_HELPERS_H_ + +#include +#include + +class SCHEMATIC; +class SCH_EDIT_FRAME; +class SETTINGS_MANAGER; +class PROJECT; + +/** + * Helper functions to do things like load schematics behind the scenes for special functions + * + * Similar to the pcbnew scripting helpers, this is just to have one spot + * for these types of "hacky" solutions + */ +class EESCHEMA_HELPERS +{ +public: + static SETTINGS_MANAGER* GetSettingsManager(); + static void SetSchEditFrame( SCH_EDIT_FRAME* aSchEditFrame ); + static PROJECT* GetDefaultProject(); + static SCHEMATIC* LoadSchematic( wxString& aFileName ); + static SCHEMATIC* LoadSchematic( wxString& aFileName, SCH_IO_MGR::SCH_FILE_T aFormat ); + + +private: + static SCH_EDIT_FRAME* s_SchEditFrame; + static SETTINGS_MANAGER* s_SettingsManager; +}; + +#endif \ No newline at end of file diff --git a/eeschema/eeschema_jobs_handler.cpp b/eeschema/eeschema_jobs_handler.cpp new file mode 100644 index 0000000000..46b93d0b9c --- /dev/null +++ b/eeschema/eeschema_jobs_handler.cpp @@ -0,0 +1,111 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright (C) 1992-2022 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 "eeschema_jobs_handler.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "eeschema_helpers.h" +#include + +#include + + +EESCHEMA_JOBS_HANDLER::EESCHEMA_JOBS_HANDLER() +{ + Register( "pdf", + std::bind( &EESCHEMA_JOBS_HANDLER::JobExportPdf, this, std::placeholders::_1 ) ); + Register( "svg", + std::bind( &EESCHEMA_JOBS_HANDLER::JobExportSvg, this, std::placeholders::_1 ) ); +} + + +void EESCHEMA_JOBS_HANDLER::InitRenderSettings( KIGFX::SCH_RENDER_SETTINGS* aRenderSettings, + const wxString& aTheme, SCHEMATIC* aSch ) +{ + COLOR_SETTINGS* cs = Pgm().GetSettingsManager().GetColorSettings( aTheme ); + aRenderSettings->LoadColors( cs ); + + aRenderSettings->SetDefaultPenWidth( aSch->Settings().m_DefaultLineWidth ); + aRenderSettings->m_LabelSizeRatio = aSch->Settings().m_LabelSizeRatio; + aRenderSettings->m_TextOffsetRatio = aSch->Settings().m_TextOffsetRatio; + aRenderSettings->m_PinSymbolSize = aSch->Settings().m_PinSymbolSize; + + aRenderSettings->SetDashLengthRatio( aSch->Settings().m_DashedLineDashRatio ); + aRenderSettings->SetGapLengthRatio( aSch->Settings().m_DashedLineGapRatio ); +} + + +int EESCHEMA_JOBS_HANDLER::JobExportPdf( JOB* aJob ) +{ + JOB_EXPORT_SCH_PDF* aPdfJob = dynamic_cast( aJob ); + + SCHEMATIC* sch = EESCHEMA_HELPERS::LoadSchematic( aPdfJob->m_filename, SCH_IO_MGR::SCH_KICAD ); + std::unique_ptr renderSettings = + std::make_unique(); + InitRenderSettings( renderSettings.get(), aPdfJob->m_colorTheme, sch ); + + std::unique_ptr schPlotter = std::make_unique( sch ); + + SCH_PLOT_SETTINGS settings; + settings.m_plotAll = true; + settings.m_plotDrawingSheet = aPdfJob->m_plotDrawingSheet; + settings.m_blackAndWhite = aPdfJob->m_blackAndWhite; + settings.m_theme = aPdfJob->m_colorTheme; + settings.m_useBackgroundColor = aPdfJob->m_useBackgroundColor; + settings.m_pageSizeSelect = PAGE_SIZE_AUTO; + settings.m_outputFile = aPdfJob->m_outputFile; + + schPlotter->Plot( PLOT_FORMAT::PDF, settings, renderSettings.get(), nullptr ); + + return 0; +} + + +int EESCHEMA_JOBS_HANDLER::JobExportSvg( JOB* aJob ) +{ + JOB_EXPORT_SCH_SVG* aSvgJob = dynamic_cast( aJob ); + + SCHEMATIC* sch = EESCHEMA_HELPERS::LoadSchematic( aSvgJob->m_filename, SCH_IO_MGR::SCH_KICAD ); + std::unique_ptr renderSettings = + std::make_unique(); + InitRenderSettings( renderSettings.get(), aSvgJob->m_colorTheme, sch ); + + std::unique_ptr schPlotter = std::make_unique( sch ); + + SCH_PLOT_SETTINGS settings; + settings.m_plotAll = true; + settings.m_plotDrawingSheet = true; + settings.m_blackAndWhite = aSvgJob->m_blackAndWhite; + settings.m_theme = aSvgJob->m_colorTheme; + settings.m_pageSizeSelect = PAGE_SIZE_AUTO; + settings.m_outputDirectory = aSvgJob->m_outputDirectory; + settings.m_useBackgroundColor = aSvgJob->m_useBackgroundColor; + + schPlotter->Plot( PLOT_FORMAT::SVG, settings, renderSettings.get(), nullptr ); + + return 0; +} \ No newline at end of file diff --git a/eeschema/eeschema_jobs_handler.h b/eeschema/eeschema_jobs_handler.h new file mode 100644 index 0000000000..cb3c318e13 --- /dev/null +++ b/eeschema/eeschema_jobs_handler.h @@ -0,0 +1,57 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright (C) 1992-2022 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 EESCHEMA_JOBS_HANDLER_H +#define EESCHEMA_JOBS_HANDLER_H + +#include +#include + +namespace KIGFX +{ +class SCH_RENDER_SETTINGS; +}; + +class SCHEMATIC; + +/** + * Handles eeschema job dispatches + */ +class EESCHEMA_JOBS_HANDLER : public JOB_DISPATCHER +{ +public: + EESCHEMA_JOBS_HANDLER(); + int JobExportPdf( JOB* aJob ); + int JobExportSvg( JOB* aJob ); + + /** + * Configures the SCH_RENDER_SETTINGS object with the correct data to be used with plotting + * + * It's sort of a kludge due to the plotter depending on this object normally managed by the frame and canvas + * + * @param aRenderSettings The object to populate with working settings + * @param aTheme The theme to take color data from to stick into render settings, can be left blank for default + * @param aSch The schematic to further copy settings from to be put into aRenderSettings + */ + void InitRenderSettings( KIGFX::SCH_RENDER_SETTINGS* aRenderSettings, const wxString& aTheme, + SCHEMATIC* aSch ); +}; + +#endif \ No newline at end of file diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp index dd2b03d367..3a13656560 100644 --- a/eeschema/sch_edit_frame.cpp +++ b/eeschema/sch_edit_frame.cpp @@ -940,22 +940,6 @@ SEVERITY SCH_EDIT_FRAME::GetSeverity( int aErrorCode ) const } -wxString SCH_EDIT_FRAME::GetUniqueFilenameForCurrentSheet() -{ - // Filename is rootSheetName-sheetName-...-sheetName - // Note that we need to fetch the rootSheetName out of its filename, as the root SCH_SHEET's - // name is just a timestamp. - - wxFileName rootFn( GetCurrentSheet().at( 0 )->GetFileName() ); - wxString filename = rootFn.GetName(); - - for( unsigned i = 1; i < GetCurrentSheet().size(); i++ ) - filename += wxT( "-" ) + GetCurrentSheet().at( i )->GetName(); - - return filename; -} - - void SCH_EDIT_FRAME::OnModify() { EDA_BASE_FRAME::OnModify(); diff --git a/eeschema/sch_edit_frame.h b/eeschema/sch_edit_frame.h index 68ef5402a9..773d20d590 100644 --- a/eeschema/sch_edit_frame.h +++ b/eeschema/sch_edit_frame.h @@ -429,15 +429,6 @@ public: */ void OnPageSettingsChange() override; - /** - * @return a filename that can be used in plot and print functions for the current screen - * and sheet path. This filename is unique and must be used instead of the screen filename - * when one must create files for each sheet in the hierarchy. - * Name is <root sheet filename>-<sheet path> and has no extension. - * However if filename is too long name is <sheet filename>-<sheet number> - */ - wxString GetUniqueFilenameForCurrentSheet(); - /** * Set the m_ScreenNumber and m_NumberOfScreens members for screens. * diff --git a/eeschema/sch_plotter.cpp b/eeschema/sch_plotter.cpp new file mode 100644 index 0000000000..5fce43c584 --- /dev/null +++ b/eeschema/sch_plotter.cpp @@ -0,0 +1,1055 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2018 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2010 Lorenzo Marcantonio + * Copyright (C) 2011 Wayne Stambaugh + * Copyright (C) 1992-2022 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 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 +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + + +static const wxChar* plot_sheet_list( HPGL_PAGE_SIZE aSize ) +{ + switch( aSize ) + { + default: + case HPGL_PAGE_SIZE::DEFAULT: return nullptr; + case HPGL_PAGE_SIZE::SIZE_A5: return wxT( "A5" ); + case HPGL_PAGE_SIZE::SIZE_A4: return wxT( "A4" ); + case HPGL_PAGE_SIZE::SIZE_A3: return wxT( "A3" ); + case HPGL_PAGE_SIZE::SIZE_A2: return wxT( "A2" ); + case HPGL_PAGE_SIZE::SIZE_A1: return wxT( "A1" ); + case HPGL_PAGE_SIZE::SIZE_A0: return wxT( "A0" ); + case HPGL_PAGE_SIZE::SIZE_A: return wxT( "A" ); + case HPGL_PAGE_SIZE::SIZE_B: return wxT( "B" ); + case HPGL_PAGE_SIZE::SIZE_C: return wxT( "C" ); + case HPGL_PAGE_SIZE::SIZE_D: return wxT( "D" ); + case HPGL_PAGE_SIZE::SIZE_E: return wxT( "E" ); + } +} + + +SCH_PLOTTER::SCH_PLOTTER( SCHEMATIC* aSchematic ) : + m_schFrame( nullptr ), + m_schematic( aSchematic ) +{ + m_colorSettings = nullptr; +} + + +SCH_PLOTTER::SCH_PLOTTER( SCH_EDIT_FRAME* aFrame ) : + m_schFrame( aFrame ), + m_schematic( &aFrame->Schematic() ) +{ + m_colorSettings = nullptr; +} + + +wxFileName SCH_PLOTTER::getOutputFilenameSingle( const SCH_PLOT_SETTINGS& aPlotSettings, + REPORTER* aReporter, const wxString& aExt ) +{ + if( !aPlotSettings.m_outputFile.empty() ) + return aPlotSettings.m_outputFile; + else + { + wxString fname = m_schematic->GetUniqueFilenameForCurrentSheet(); + + // The sub sheet can be in a sub_hierarchy, but we plot the file in the main + // project folder (or the folder specified by the caller), so replace separators + // to create a unique filename: + fname.Replace( "/", "_" ); + fname.Replace( "\\", "_" ); + + return createPlotFileName( aPlotSettings, fname, aExt, aReporter ); + } + +} + + +void SCH_PLOTTER::createPDFFile( const SCH_PLOT_SETTINGS& aPlotSettings, + RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter ) +{ + SCH_SHEET_PATH oldsheetpath = m_schematic->CurrentSheet(); // sheetpath is saved here + + /* When printing all pages, the printed page is not the current page. In complex hierarchies, + * we must update symbol references and other parameters in the given printed SCH_SCREEN, + * according to the sheet path because in complex hierarchies a SCH_SCREEN (a drawing ) is + * shared between many sheets and symbol references depend on the actual sheet path used. + */ + SCH_SHEET_LIST sheetList; + + if( aPlotSettings.m_plotAll ) + { + sheetList.BuildSheetList( &m_schematic->Root(), true ); + sheetList.SortByPageNumbers(); + } + else + { + sheetList.push_back( m_schematic->CurrentSheet() ); + } + + // Allocate the plotter and set the job level parameter + PDF_PLOTTER* plotter = new PDF_PLOTTER(); + plotter->SetRenderSettings( aRenderSettings ); + plotter->SetColorMode( !aPlotSettings.m_blackAndWhite ); + plotter->SetCreator( wxT( "Eeschema-PDF" ) ); + plotter->SetTitle( ExpandTextVars( m_schematic->RootScreen()->GetTitleBlock().GetTitle(), + &m_schematic->Prj() ) ); + + wxString msg; + wxFileName plotFileName; + LOCALE_IO toggle; // Switch the locale to standard C + + for( unsigned i = 0; i < sheetList.size(); i++ ) + { + if( m_schFrame ) + m_schFrame->SetCurrentSheet( sheetList[i] ); + else + m_schematic->SetCurrentSheet( sheetList[i] ); + m_schematic->CurrentSheet().UpdateAllScreenReferences(); + + if( m_schFrame ) + m_schFrame->SetSheetNumberAndCount(); + + SCH_SCREEN* screen = m_schematic->CurrentSheet().LastScreen(); + + if( i == 0 ) + { + try + { + wxString ext = PDF_PLOTTER::GetDefaultFileExtension(); + plotFileName = getOutputFilenameSingle( aPlotSettings, aReporter, ext ); + + m_lastOutputFilePath = plotFileName.GetFullPath(); + + if( !plotFileName.IsOk() ) + return; + + if( !plotter->OpenFile( plotFileName.GetFullPath() ) ) + { + if( aReporter ) + { + msg.Printf( _( "Failed to create file '%s'." ), + plotFileName.GetFullPath() ); + aReporter->Report( msg, RPT_SEVERITY_ERROR ); + } + delete plotter; + return; + } + + // Open the plotter and do the first page + setupPlotPagePDF( plotter, screen, aPlotSettings ); + plotter->StartPlot( sheetList[i].GetPageNumber(), _( "Root" ) ); + } + catch( const IO_ERROR& e ) + { + // Cannot plot PDF file + if( aReporter ) + { + msg.Printf( wxT( "PDF Plotter exception: %s" ), e.What() ); + aReporter->Report( msg, RPT_SEVERITY_ERROR ); + } + + restoreEnvironment( plotter, oldsheetpath ); + return; + } + } + else + { + /* For the following pages you need to close the (finished) page, + * reconfigure, and then start a new one */ + plotter->ClosePage(); + setupPlotPagePDF( plotter, screen, aPlotSettings ); + plotter->StartPage( sheetList[i].GetPageNumber(), + sheetList[i].Last()->GetFields()[SHEETNAME].GetShownText() ); + } + + plotOneSheetPDF( plotter, screen, aPlotSettings ); + } + + // Everything done, close the plot and restore the environment + if( aReporter ) + { + msg.Printf( _( "Plotted to '%s'.\n" ), plotFileName.GetFullPath() ); + aReporter->Report( msg, RPT_SEVERITY_ACTION ); + aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO ); + } + + restoreEnvironment( plotter, oldsheetpath ); +} + + +void SCH_PLOTTER::plotOneSheetPDF( PLOTTER* aPlotter, SCH_SCREEN* aScreen, + const SCH_PLOT_SETTINGS& aPlotSettings ) +{ + if( aPlotSettings.m_useBackgroundColor && aPlotter->GetColorMode() ) + { + aPlotter->SetColor( aPlotter->RenderSettings()->GetBackgroundColor() ); + wxPoint end( aPlotter->PageSettings().GetWidthIU( schIUScale.IU_PER_MILS ), + aPlotter->PageSettings().GetHeightIU( schIUScale.IU_PER_MILS ) ); + aPlotter->Rect( wxPoint( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 ); + } + + if( aPlotSettings.m_plotDrawingSheet ) + { + COLOR4D color = COLOR4D::BLACK; + + if( aPlotter->GetColorMode() ) + color = aPlotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_DRAWINGSHEET ); + + wxString sheetName = m_schematic->CurrentSheet().Last()->GetName(); + wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable(); + + PlotDrawingSheet( aPlotter, &aScreen->Schematic()->Prj(), + m_schematic->RootScreen()->GetTitleBlock(), + aPlotter->PageSettings(), + aScreen->Schematic()->GetProperties(), + aScreen->GetPageNumber(), aScreen->GetPageCount(), sheetName, sheetPath, + aScreen->GetFileName(), color, aScreen->GetVirtualPageNumber() == 1 ); + } + + aScreen->Plot( aPlotter ); +} + + +void SCH_PLOTTER::setupPlotPagePDF( PLOTTER* aPlotter, SCH_SCREEN* aScreen, + const SCH_PLOT_SETTINGS& aPlotSettings ) +{ + PAGE_INFO plotPage; // page size selected to plot + + // Considerations on page size and scaling requests + const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic + + switch( aPlotSettings.m_pageSizeSelect ) + { + case PAGE_SIZE_A: + plotPage.SetType( wxT( "A" ) ); + plotPage.SetPortrait( actualPage.IsPortrait() ); + break; + + case PAGE_SIZE_A4: + plotPage.SetType( wxT( "A4" ) ); + plotPage.SetPortrait( actualPage.IsPortrait() ); + break; + + case PAGE_SIZE_AUTO: + default: + plotPage = actualPage; + break; + } + + double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils(); + double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils(); + double scale = std::min( scalex, scaley ); + aPlotter->SetPageSettings( plotPage ); + + // Currently, plot units are in decimil + aPlotter->SetViewport( wxPoint( 0, 0 ), schIUScale.IU_PER_MILS/10, scale, false ); +} + + +void SCH_PLOTTER::createPSFiles( const SCH_PLOT_SETTINGS& aPlotSettings, + RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter ) +{ + SCH_SHEET_PATH oldsheetpath = m_schematic->CurrentSheet(); // sheetpath is saved here + PAGE_INFO plotPage; // page size selected to plot + wxString msg; + + /* When printing all pages, the printed page is not the current page. + * In complex hierarchies, we must update symbol references and other parameters in the + * given printed SCH_SCREEN, accordant to the sheet path because in complex hierarchies + * a SCH_SCREEN (a drawing ) is shared between many sheets and symbol references + * depend on the actual sheet path used. + */ + SCH_SHEET_LIST sheetList; + + if( aPlotSettings.m_plotAll ) + { + sheetList.BuildSheetList( &m_schematic->Root(), true ); + sheetList.SortByPageNumbers(); + } + else + { + sheetList.push_back( m_schematic->CurrentSheet() ); + } + + for( unsigned i = 0; i < sheetList.size(); i++ ) + { + if( m_schFrame ) + m_schFrame->SetCurrentSheet( sheetList[i] ); + else + m_schematic->SetCurrentSheet( sheetList[i] ); + + m_schematic->CurrentSheet().UpdateAllScreenReferences(); + + if( m_schFrame ) + m_schFrame->SetSheetNumberAndCount(); + + SCH_SCREEN* screen = m_schematic->CurrentSheet().LastScreen(); + PAGE_INFO actualPage = screen->GetPageSettings(); + + switch( aPlotSettings.m_pageSizeSelect ) + { + case PAGE_SIZE_A: + plotPage.SetType( wxT( "A" ) ); + plotPage.SetPortrait( actualPage.IsPortrait() ); + break; + + case PAGE_SIZE_A4: + plotPage.SetType( wxT( "A4" ) ); + plotPage.SetPortrait( actualPage.IsPortrait() ); + break; + + case PAGE_SIZE_AUTO: + default: plotPage = actualPage; break; + } + + double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils(); + double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils(); + double scale = std::min( scalex, scaley ); + wxPoint plot_offset; + + try + { + wxString fname = m_schematic->GetUniqueFilenameForCurrentSheet(); + + // The sub sheet can be in a sub_hierarchy, but we plot the file in the + // main project folder (or the folder specified by the caller), + // so replace separators to create a unique filename: + fname.Replace( "/", "_" ); + fname.Replace( "\\", "_" ); + wxString ext = PS_PLOTTER::GetDefaultFileExtension(); + wxFileName plotFileName = createPlotFileName( aPlotSettings, fname, ext, aReporter ); + + m_lastOutputFilePath = plotFileName.GetFullPath(); + + if( !plotFileName.IsOk() ) + return; + + if( plotOneSheetPS( plotFileName.GetFullPath(), screen, aRenderSettings, plotPage, + plot_offset, scale, aPlotSettings ) ) + { + if( aReporter ) + { + msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() ); + aReporter->Report( msg, RPT_SEVERITY_ACTION ); + } + } + else + { + if( aReporter ) + { + // Error + msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() ); + aReporter->Report( msg, RPT_SEVERITY_ERROR ); + } + } + } + catch( IO_ERROR& e ) + { + if( aReporter ) + { + msg.Printf( wxT( "PS Plotter exception: %s" ), e.What() ); + aReporter->Report( msg, RPT_SEVERITY_ERROR ); + } + } + } + + if( aReporter ) + { + aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO ); + } + + if( m_schFrame ) + m_schFrame->SetCurrentSheet( oldsheetpath ); + else + m_schematic->SetCurrentSheet( oldsheetpath ); + + m_schematic->CurrentSheet().UpdateAllScreenReferences(); + + if( m_schFrame ) + m_schFrame->SetSheetNumberAndCount(); +} + + +bool SCH_PLOTTER::plotOneSheetPS( const wxString& aFileName, SCH_SCREEN* aScreen, + RENDER_SETTINGS* aRenderSettings, + const PAGE_INFO& aPageInfo, const wxPoint& aPlot0ffset, + double aScale, const SCH_PLOT_SETTINGS& aPlotSettings ) +{ + PS_PLOTTER* plotter = new PS_PLOTTER(); + plotter->SetRenderSettings( aRenderSettings ); + plotter->SetPageSettings( aPageInfo ); + plotter->SetColorMode( !aPlotSettings.m_blackAndWhite ); + + // Currently, plot units are in decimil + plotter->SetViewport( aPlot0ffset, schIUScale.IU_PER_MILS / 10, aScale, false ); + + // Init : + plotter->SetCreator( wxT( "Eeschema-PS" ) ); + + if( !plotter->OpenFile( aFileName ) ) + { + delete plotter; + return false; + } + + LOCALE_IO toggle; // Switch the locale to standard C + + plotter->StartPlot( m_schematic->CurrentSheet().GetPageNumber() ); + + if( aPlotSettings.m_useBackgroundColor && plotter->GetColorMode() ) + { + plotter->SetColor( plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) ); + + wxPoint end( plotter->PageSettings().GetWidthIU( schIUScale.IU_PER_MILS ), + plotter->PageSettings().GetHeightIU( schIUScale.IU_PER_MILS ) ); + plotter->Rect( wxPoint( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 ); + } + + if( aPlotSettings.m_plotDrawingSheet ) + { + wxString sheetName = m_schematic->CurrentSheet().Last()->GetName(); + wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable(); + COLOR4D color = plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_DRAWINGSHEET ); + + PlotDrawingSheet( plotter, &aScreen->Schematic()->Prj(), + m_schematic->RootScreen()->GetTitleBlock(), + aPageInfo, aScreen->Schematic()->GetProperties(), + aScreen->GetPageNumber(), aScreen->GetPageCount(), sheetName, sheetPath, + aScreen->GetFileName(), plotter->GetColorMode() ? color : COLOR4D::BLACK, + aScreen->GetVirtualPageNumber() == 1 ); + } + + aScreen->Plot( plotter ); + + plotter->EndPlot(); + delete plotter; + + return true; +} + + +void SCH_PLOTTER::createSVGFiles( const SCH_PLOT_SETTINGS& aPlotSettings, + RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter ) +{ + wxString msg; + SCH_SHEET_PATH oldsheetpath = m_schematic->CurrentSheet(); + SCH_SHEET_LIST sheetList; + + if( aPlotSettings.m_plotAll ) + { + sheetList.BuildSheetList( &m_schematic->Root(), true ); + sheetList.SortByPageNumbers(); + } + else + { + sheetList.push_back( m_schematic->CurrentSheet() ); + } + + for( unsigned i = 0; i < sheetList.size(); i++ ) + { + SCH_SCREEN* screen; + if( m_schFrame ) + m_schFrame->SetCurrentSheet( sheetList[i] ); + else + m_schematic->SetCurrentSheet( sheetList[i] ); + + m_schematic->CurrentSheet().UpdateAllScreenReferences(); + + if( m_schFrame ) + m_schFrame->SetSheetNumberAndCount(); + + screen = m_schematic->CurrentSheet().LastScreen(); + + try + { + wxString fname = m_schematic->GetUniqueFilenameForCurrentSheet(); + + // The sub sheet can be in a sub_hierarchy, but we plot the file in the + // main project folder (or the folder specified by the caller), + // so replace separators to create a unique filename: + fname.Replace( "/", "_" ); + fname.Replace( "\\", "_" ); + wxString ext = SVG_PLOTTER::GetDefaultFileExtension(); + wxFileName plotFileName = createPlotFileName( aPlotSettings, fname, ext, aReporter ); + + m_lastOutputFilePath = plotFileName.GetFullPath(); + + if( !plotFileName.IsOk() ) + return; + + bool success = plotOneSheetSVG( plotFileName.GetFullPath(), screen, aRenderSettings, + aPlotSettings ); + + if( !success ) + { + if( aReporter ) + { + msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() ); + aReporter->Report( msg, RPT_SEVERITY_ERROR ); + } + } + else + { + if( aReporter ) + { + msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() ); + aReporter->Report( msg, RPT_SEVERITY_ACTION ); + } + } + } + catch( const IO_ERROR& e ) + { + if( aReporter ) + { + // Cannot plot SVG file + msg.Printf( wxT( "SVG Plotter exception: %s" ), e.What() ); + aReporter->Report( msg, RPT_SEVERITY_ERROR ); + } + break; + } + } + + if( aReporter ) + { + aReporter->ReportTail( _( "Done" ), RPT_SEVERITY_INFO ); + } + + if( m_schFrame ) + m_schFrame->SetCurrentSheet( oldsheetpath ); + else + m_schematic->SetCurrentSheet( oldsheetpath ); + + m_schematic->CurrentSheet().UpdateAllScreenReferences(); + + if( m_schFrame ) + m_schFrame->SetSheetNumberAndCount(); +} + + +bool SCH_PLOTTER::plotOneSheetSVG( const wxString& aFileName, SCH_SCREEN* aScreen, + RENDER_SETTINGS* aRenderSettings, + const SCH_PLOT_SETTINGS& aPlotSettings ) +{ + const PAGE_INFO& pageInfo = aScreen->GetPageSettings(); + + SVG_PLOTTER* plotter = new SVG_PLOTTER(); + plotter->SetRenderSettings( aRenderSettings ); + plotter->SetPageSettings( pageInfo ); + plotter->SetColorMode( aPlotSettings.m_blackAndWhite ? false : true ); + wxPoint plot_offset; + double scale = 1.0; + + // Currently, plot units are in decimil + plotter->SetViewport( plot_offset, schIUScale.IU_PER_MILS / 10, scale, false ); + + // Init : + plotter->SetCreator( wxT( "Eeschema-SVG" ) ); + + if( !plotter->OpenFile( aFileName ) ) + { + delete plotter; + return false; + } + + LOCALE_IO toggle; + + plotter->StartPlot( m_schematic->CurrentSheet().GetPageNumber() ); + + if( aPlotSettings.m_useBackgroundColor && plotter->GetColorMode() ) + { + plotter->SetColor( plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) ); + wxPoint end( plotter->PageSettings().GetWidthIU( schIUScale.IU_PER_MILS ), + plotter->PageSettings().GetHeightIU( schIUScale.IU_PER_MILS ) ); + plotter->Rect( wxPoint( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 ); + } + + if( aPlotSettings.m_plotDrawingSheet ) + { + wxString sheetName = m_schematic->CurrentSheet().Last()->GetName(); + wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable(); + COLOR4D color = plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_DRAWINGSHEET ); + + PlotDrawingSheet( plotter, &aScreen->Schematic()->Prj(), + m_schematic->RootScreen()->GetTitleBlock(), + pageInfo, aScreen->Schematic()->GetProperties(), aScreen->GetPageNumber(), + aScreen->GetPageCount(), sheetName, sheetPath, aScreen->GetFileName(), + plotter->GetColorMode() ? color : COLOR4D::BLACK, + aScreen->GetVirtualPageNumber() == 1 ); + } + + aScreen->Plot( plotter ); + + plotter->EndPlot(); + delete plotter; + + return true; +} + + +void SCH_PLOTTER::createHPGLFiles( const SCH_PLOT_SETTINGS& aPlotSettings, + RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter ) +{ + SCH_SCREEN* screen = m_schematic->RootScreen(); + SCH_SHEET_PATH oldsheetpath = m_schematic->CurrentSheet(); + + /* When printing all pages, the printed page is not the current page. In complex hierarchies, + * we must update symbol references and other parameters in the given printed SCH_SCREEN, + * according to the sheet path because in complex hierarchies a SCH_SCREEN (a drawing ) is + * shared between many sheets and symbol references depend on the actual sheet path used. + */ + SCH_SHEET_LIST sheetList; + + if( aPlotSettings.m_plotAll ) + { + sheetList.BuildSheetList( &m_schematic->Root(), true ); + sheetList.SortByPageNumbers(); + } + else + { + sheetList.push_back( m_schematic->CurrentSheet() ); + } + + for( unsigned i = 0; i < sheetList.size(); i++ ) + { + if( m_schFrame ) + m_schFrame->SetCurrentSheet( sheetList[i] ); + else + m_schematic->SetCurrentSheet( sheetList[i] ); + m_schematic->CurrentSheet().UpdateAllScreenReferences(); + + if( m_schFrame ) + m_schFrame->SetSheetNumberAndCount(); + + screen = m_schematic->CurrentSheet().LastScreen(); + + if( !screen ) // LastScreen() may return NULL + screen = m_schematic->RootScreen(); + + const PAGE_INFO& curPage = screen->GetPageSettings(); + + PAGE_INFO plotPage = curPage; + + // if plotting on a page size other than curPage + plotPage.SetType( plot_sheet_list( aPlotSettings.m_HPGLPaperSizeSelect ) ); + + // Calculation of conversion scales. + double plot_scale = (double) plotPage.GetWidthMils() / curPage.GetWidthMils(); + + // Calculate offsets + wxPoint plotOffset; + wxString msg; + + if( aPlotSettings.m_HPGLPlotOrigin == HPGL_PLOT_ORIGIN_AND_UNITS::PLOTTER_CENTER ) + { + plotOffset.x = plotPage.GetWidthIU( schIUScale.IU_PER_MILS ) / 2; + plotOffset.y = -plotPage.GetHeightIU( schIUScale.IU_PER_MILS ) / 2; + } + + try + { + wxString fname = m_schematic->GetUniqueFilenameForCurrentSheet(); + // The sub sheet can be in a sub_hierarchy, but we plot the file in the + // main project folder (or the folder specified by the caller), + // so replace separators to create a unique filename: + fname.Replace( "/", "_" ); + fname.Replace( "\\", "_" ); + wxString ext = HPGL_PLOTTER::GetDefaultFileExtension(); + wxFileName plotFileName = createPlotFileName( aPlotSettings, fname, ext, aReporter ); + + if( !plotFileName.IsOk() ) + return; + + LOCALE_IO toggle; + + if( plotOneSheetHpgl( plotFileName.GetFullPath(), screen, plotPage, aRenderSettings, + plotOffset, plot_scale, aPlotSettings ) ) + { + if( aReporter ) + { + msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() ); + aReporter->Report( msg, RPT_SEVERITY_ACTION ); + } + } + else + { + if( aReporter ) + { + msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() ); + aReporter->Report( msg, RPT_SEVERITY_ERROR ); + } + } + } + catch( IO_ERROR& e ) + { + if( aReporter ) + { + msg.Printf( wxT( "HPGL Plotter exception: %s" ), e.What() ); + aReporter->Report( msg, RPT_SEVERITY_ERROR ); + } + } + } + + if( aReporter ) + { + aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO ); + } + + if( m_schFrame ) + m_schFrame->SetCurrentSheet( oldsheetpath ); + else + m_schematic->SetCurrentSheet( oldsheetpath ); + + m_schematic->CurrentSheet().UpdateAllScreenReferences(); + + if( m_schFrame ) + m_schFrame->SetSheetNumberAndCount(); +} + + +bool SCH_PLOTTER::plotOneSheetHpgl( const wxString& aFileName, + SCH_SCREEN* aScreen, + const PAGE_INFO& aPageInfo, + RENDER_SETTINGS* aRenderSettings, + const wxPoint& aPlot0ffset, + double aScale, + const SCH_PLOT_SETTINGS& aPlotSettings ) +{ + HPGL_PLOTTER* plotter = new HPGL_PLOTTER(); + // Currently, plot units are in decimil + + plotter->SetPageSettings( aPageInfo ); + plotter->SetRenderSettings( aRenderSettings ); + plotter->RenderSettings()->LoadColors( m_colorSettings ); + plotter->SetColorMode( !aPlotSettings.m_blackAndWhite ); + plotter->SetViewport( aPlot0ffset, schIUScale.IU_PER_MILS/10, aScale, false ); + + // TODO this could be configurable + plotter->SetTargetChordLength( schIUScale.mmToIU( 0.6 ) ); + + switch( aPlotSettings.m_HPGLPlotOrigin ) + { + case HPGL_PLOT_ORIGIN_AND_UNITS::PLOTTER_BOT_LEFT: + case HPGL_PLOT_ORIGIN_AND_UNITS::PLOTTER_CENTER: + default: + plotter->SetUserCoords( false ); + break; + case HPGL_PLOT_ORIGIN_AND_UNITS::USER_FIT_PAGE: + plotter->SetUserCoords( true ); + plotter->SetUserCoordsFit( false ); + break; + case HPGL_PLOT_ORIGIN_AND_UNITS::USER_FIT_CONTENT: + plotter->SetUserCoords( true ); + plotter->SetUserCoordsFit( true ); + break; + } + + // Init : + plotter->SetCreator( wxT( "Eeschema-HPGL" ) ); + + if( !plotter->OpenFile( aFileName ) ) + { + delete plotter; + return false; + } + + LOCALE_IO toggle; + + // Pen num and pen speed are not initialized here. + // Default HPGL driver values are used + plotter->SetPenDiameter( aPlotSettings.m_HPGLPenSize ); + plotter->StartPlot( m_schematic->CurrentSheet().GetPageNumber() ); + + if( aPlotSettings.m_plotDrawingSheet ) + { + wxString sheetName = m_schematic->CurrentSheet().Last()->GetName(); + wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable(); + + PlotDrawingSheet( plotter, &m_schematic->Prj(), m_schematic->RootScreen()->GetTitleBlock(), + aPageInfo, + aScreen->Schematic()->GetProperties(), aScreen->GetPageNumber(), + aScreen->GetPageCount(), sheetName, sheetPath, aScreen->GetFileName(), + COLOR4D::BLACK, aScreen->GetVirtualPageNumber() == 1 ); + } + + aScreen->Plot( plotter ); + + plotter->EndPlot(); + delete plotter; + + return true; +} + + +void SCH_PLOTTER::createDXFFiles( const SCH_PLOT_SETTINGS& aPlotSettings, + RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter ) +{ + SCH_SHEET_PATH oldsheetpath = m_schematic->CurrentSheet(); + + /* When printing all pages, the printed page is not the current page. In complex hierarchies, + * we must update symbol references and other parameters in the given printed SCH_SCREEN, + * according to the sheet path because in complex hierarchies a SCH_SCREEN (a drawing ) is + * shared between many sheets and symbol references depend on the actual sheet path used. + */ + SCH_SHEET_LIST sheetList; + + if( aPlotSettings.m_plotAll ) + { + sheetList.BuildSheetList( &m_schematic->Root(), true ); + sheetList.SortByPageNumbers(); + } + else + { + sheetList.push_back( m_schematic->CurrentSheet() ); + } + + for( unsigned i = 0; i < sheetList.size(); i++ ) + { + if( m_schFrame ) + m_schFrame->SetCurrentSheet( sheetList[i] ); + else + m_schematic->SetCurrentSheet( sheetList[i] ); + m_schematic->CurrentSheet().UpdateAllScreenReferences(); + + if( m_schFrame ) + m_schFrame->SetSheetNumberAndCount(); + + SCH_SCREEN* screen = m_schematic->CurrentSheet().LastScreen(); + wxPoint plot_offset; + wxString msg; + + try + { + wxString fname = m_schematic->GetUniqueFilenameForCurrentSheet(); + + // The sub sheet can be in a sub_hierarchy, but we plot the file in the + // main project folder (or the folder specified by the caller), + // so replace separators to create a unique filename: + fname.Replace( "/", "_" ); + fname.Replace( "\\", "_" ); + wxString ext = DXF_PLOTTER::GetDefaultFileExtension(); + wxFileName plotFileName = createPlotFileName( aPlotSettings, fname, ext, aReporter ); + + m_lastOutputFilePath = plotFileName.GetFullPath(); + + if( !plotFileName.IsOk() ) + return; + + if( plotOneSheetDXF( plotFileName.GetFullPath(), screen, aRenderSettings, plot_offset, + 1.0, aPlotSettings ) ) + { + if( aReporter ) + { + msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() ); + aReporter->Report( msg, RPT_SEVERITY_ACTION ); + } + } + else // Error + { + if( aReporter ) + { + msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() ); + aReporter->Report( msg, RPT_SEVERITY_ERROR ); + } + } + } + catch( IO_ERROR& e ) + { + if( aReporter ) + { + msg.Printf( wxT( "DXF Plotter exception: %s" ), e.What() ); + aReporter->Report( msg, RPT_SEVERITY_ERROR ); + } + + if( m_schFrame ) + m_schFrame->SetCurrentSheet( oldsheetpath ); + else + m_schematic->SetCurrentSheet( oldsheetpath ); + + m_schematic->CurrentSheet().UpdateAllScreenReferences(); + + if( m_schFrame ) + m_schFrame->SetSheetNumberAndCount(); + return; + } + } + + if( aReporter ) + aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO ); + + if( m_schFrame ) + m_schFrame->SetCurrentSheet( oldsheetpath ); + else + m_schematic->SetCurrentSheet( oldsheetpath ); + + m_schematic->CurrentSheet().UpdateAllScreenReferences(); + + if( m_schFrame ) + m_schFrame->SetSheetNumberAndCount(); +} + + +bool SCH_PLOTTER::plotOneSheetDXF( const wxString& aFileName, SCH_SCREEN* aScreen, + RENDER_SETTINGS* aRenderSettings, const wxPoint& aPlotOffset, + double aScale, const SCH_PLOT_SETTINGS& aPlotSettings ) +{ + aRenderSettings->LoadColors( m_colorSettings ); + aRenderSettings->SetDefaultPenWidth( 0 ); + + const PAGE_INFO& pageInfo = aScreen->GetPageSettings(); + DXF_PLOTTER* plotter = new DXF_PLOTTER(); + + plotter->SetRenderSettings( aRenderSettings ); + plotter->SetPageSettings( pageInfo ); + plotter->SetColorMode( !aPlotSettings.m_blackAndWhite ); + + // Currently, plot units are in decimil + plotter->SetViewport( aPlotOffset, schIUScale.IU_PER_MILS / 10, aScale, false ); + + // Init : + plotter->SetCreator( wxT( "Eeschema-DXF" ) ); + + if( !plotter->OpenFile( aFileName ) ) + { + delete plotter; + return false; + } + + LOCALE_IO toggle; + + plotter->StartPlot( m_schematic->CurrentSheet().GetPageNumber() ); + + if( aPlotSettings.m_plotDrawingSheet ) + { + wxString sheetName = m_schematic->CurrentSheet().Last()->GetName(); + wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable(); + COLOR4D color = plotter->RenderSettings()->GetLayerColor( LAYER_SCHEMATIC_DRAWINGSHEET ); + + PlotDrawingSheet( plotter, &m_schematic->Prj(), m_schematic->RootScreen()->GetTitleBlock(), + pageInfo, + aScreen->Schematic()->GetProperties(), aScreen->GetPageNumber(), + aScreen->GetPageCount(), sheetName, sheetPath, aScreen->GetFileName(), + plotter->GetColorMode() ? color : COLOR4D::BLACK, + aScreen->GetVirtualPageNumber() == 1 ); + } + + aScreen->Plot( plotter ); + + // finish + plotter->EndPlot(); + delete plotter; + + return true; +} + + +void SCH_PLOTTER::restoreEnvironment( PDF_PLOTTER* aPlotter, SCH_SHEET_PATH& aOldsheetpath ) +{ + aPlotter->EndPlot(); + delete aPlotter; + + // Restore the previous sheet + if( m_schFrame ) + m_schFrame->SetCurrentSheet( aOldsheetpath ); + else + m_schematic->SetCurrentSheet( aOldsheetpath ); + + m_schematic->CurrentSheet().UpdateAllScreenReferences(); + + if( m_schFrame ) + m_schFrame->SetSheetNumberAndCount(); +} + + +wxFileName SCH_PLOTTER::createPlotFileName( const SCH_PLOT_SETTINGS& aPlotSettings, + const wxString& aPlotFileName, + const wxString& aExtension, REPORTER* aReporter ) +{ + wxFileName retv; + wxFileName tmp; + + tmp.SetPath( aPlotSettings.m_outputDirectory ); + retv.SetPath( tmp.GetPath() ); + + if( !aPlotFileName.IsEmpty() ) + retv.SetName( aPlotFileName ); + else + retv.SetName( _( "Schematic" ) ); + + retv.SetExt( aExtension ); + + if( !EnsureFileDirectoryExists( &tmp, retv.GetFullName(), aReporter ) || !tmp.IsDirWritable() ) + { + if( aReporter ) + { + wxString msg = wxString::Format( _( "Failed to write plot files to folder '%s'." ), + tmp.GetPath() ); + aReporter->Report( msg, RPT_SEVERITY_ERROR ); + } + retv.Clear(); + + SCHEMATIC_SETTINGS& settings = m_schematic->Settings(); + settings.m_PlotDirectoryName.Clear(); + } + else + { + retv.SetPath( tmp.GetPath() ); + } + + wxLogTrace( tracePathsAndFiles, "Writing plot file '%s'.", retv.GetFullPath() ); + + return retv; +} + + +void SCH_PLOTTER::Plot( PLOT_FORMAT aPlotFormat, const SCH_PLOT_SETTINGS& aPlotSettings, + RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter ) +{ + SETTINGS_MANAGER& settingsMgr = Pgm().GetSettingsManager(); + + m_colorSettings = settingsMgr.GetColorSettings( aPlotSettings.m_theme ); + + switch( aPlotFormat ) + { + default: + case PLOT_FORMAT::POST: createPSFiles( aPlotSettings, aRenderSettings, aReporter ); break; + case PLOT_FORMAT::DXF: createDXFFiles( aPlotSettings, aRenderSettings, aReporter ); break; + case PLOT_FORMAT::PDF: createPDFFile( aPlotSettings, aRenderSettings, aReporter ); break; + case PLOT_FORMAT::SVG: createSVGFiles( aPlotSettings, aRenderSettings, aReporter ); break; + case PLOT_FORMAT::HPGL: createHPGLFiles( aPlotSettings, aRenderSettings, aReporter ); break; + } +} \ No newline at end of file diff --git a/eeschema/sch_plotter.h b/eeschema/sch_plotter.h new file mode 100644 index 0000000000..d1e84cb91e --- /dev/null +++ b/eeschema/sch_plotter.h @@ -0,0 +1,221 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2018 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2010 Lorenzo Marcantonio + * Copyright (C) 2011 Wayne Stambaugh + * Copyright (C) 1992-2022 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 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 + */ + +#ifndef SCH_PLOTTER_H +#define SCH_PLOTTER_H + +#include +#include +#include +#include +#include +#include + +class SCH_EDIT_FRAME; +class PLOTTER; +class SCHEMATIC; +class SCH_SCREEN; +using KIGFX::RENDER_SETTINGS; +class PDF_PLOTTER; +class REPORTER; + +enum class HPGL_PLOT_ORIGIN_AND_UNITS +{ + PLOTTER_BOT_LEFT, + PLOTTER_CENTER, + USER_FIT_PAGE, + USER_FIT_CONTENT, +}; + + +enum PageFormatReq +{ + PAGE_SIZE_AUTO, + PAGE_SIZE_A4, + PAGE_SIZE_A +}; + + +enum class HPGL_PAGE_SIZE +{ + DEFAULT = 0, + SIZE_A5, + SIZE_A4, + SIZE_A3, + SIZE_A2, + SIZE_A1, + SIZE_A0, + SIZE_A, + SIZE_B, + SIZE_C, + SIZE_D, + SIZE_E, +}; + + +struct SCH_PLOT_SETTINGS +{ + bool m_plotAll; + bool m_plotDrawingSheet; + bool m_blackAndWhite; + int m_pageSizeSelect; + bool m_useBackgroundColor; + double m_HPGLPenSize; // for HPGL format only: pen size + HPGL_PAGE_SIZE m_HPGLPaperSizeSelect; + wxString m_theme; + + wxString m_outputDirectory; + wxString m_outputFile; + + HPGL_PLOT_ORIGIN_AND_UNITS m_HPGLPlotOrigin; + + SCH_PLOT_SETTINGS() : + m_plotAll( true ), + m_plotDrawingSheet( true ), + m_pageSizeSelect( 0 ), + m_useBackgroundColor( true ), + m_HPGLPenSize( 1.0 ), + m_HPGLPaperSizeSelect( HPGL_PAGE_SIZE::DEFAULT ), + m_theme(), + m_outputDirectory(), + m_outputFile(), + m_HPGLPlotOrigin( HPGL_PLOT_ORIGIN_AND_UNITS::USER_FIT_CONTENT ) + { + + } +}; + + +/** + * Schematic plotting class + */ +class SCH_PLOTTER +{ +public: + /** + * Constructor for usage with a frame having the schematic we want to print loaded + */ + SCH_PLOTTER( SCH_EDIT_FRAME* aFrame ); + + /** + * Constructor for usage with a schematic that can be headless + */ + SCH_PLOTTER( SCHEMATIC* aSch ); + + /** + * Perform the plotting of the schematic using the given aPlotFormat and aPlotSettings + * + * @param aPlotFormat The resulting output plot format (PDF, SVG, DXF, etc) + * @param aPlotSettings The configuration for the plotting operation + * @param aRenderSettings Mandatory object containing render settings for lower level classes + * @param aReporter Optional reporter to print messages to + */ + void Plot( PLOT_FORMAT aPlotFormat, const SCH_PLOT_SETTINGS& aPlotSettings, + RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter = nullptr ); + + /** + * Get the last output file path, this is mainly intended for PDFs with the open after plot GUI option + */ + wxString GetLastOutputFilePath() const { return m_lastOutputFilePath; } + +protected: + /** + * Returns the output filename for formats where the output is a single file + */ + wxFileName getOutputFilenameSingle( const SCH_PLOT_SETTINGS& aPlotSettings, REPORTER* aReporter, + const wxString& ext ); + + // PDF + void createPDFFile( const SCH_PLOT_SETTINGS& aPlotSettings, RENDER_SETTINGS* aRenderSettings, + REPORTER* aReporter ); + void plotOneSheetPDF( PLOTTER* aPlotter, SCH_SCREEN* aScreen, + const SCH_PLOT_SETTINGS& aPlotSettings ); + void setupPlotPagePDF( PLOTTER* aPlotter, SCH_SCREEN* aScreen, + const SCH_PLOT_SETTINGS& aPlotSettings ); + + // DXF + void createDXFFiles( const SCH_PLOT_SETTINGS& aPlotSettings, RENDER_SETTINGS* aRenderSettings, + REPORTER* aReporter ); + bool plotOneSheetDXF( const wxString& aFileName, SCH_SCREEN* aScreen, + RENDER_SETTINGS* aRenderSettings, const wxPoint& aPlotOffset, + double aScale, const SCH_PLOT_SETTINGS& aPlotSettings ); + + + // HPGL + void createHPGLFiles( const SCH_PLOT_SETTINGS& aPlotSettings, RENDER_SETTINGS* aRenderSettings, + REPORTER* aReporter ); + bool plotOneSheetHpgl( const wxString& aFileName, SCH_SCREEN* aScreen, + const PAGE_INFO& aPageInfo, RENDER_SETTINGS* aRenderSettings, + const wxPoint& aPlot0ffset, double aScale, + const SCH_PLOT_SETTINGS& aPlotSettings ); + + // PS + void createPSFiles( const SCH_PLOT_SETTINGS& aPlotSettings, RENDER_SETTINGS* aRenderSettings, + REPORTER* aReporter ); + bool plotOneSheetPS( const wxString& aFileName, SCH_SCREEN* aScreen, + RENDER_SETTINGS* aRenderSettings, const PAGE_INFO& aPageInfo, + const wxPoint& aPlot0ffset, double aScale, + const SCH_PLOT_SETTINGS& aPlotSettings ); + + // SVG + void createSVGFiles( const SCH_PLOT_SETTINGS& aPlotSettings, RENDER_SETTINGS* aRenderSettings, + REPORTER* aReporter ); + bool plotOneSheetSVG( const wxString& aFileName, SCH_SCREEN* aScreen, + RENDER_SETTINGS* aRenderSettings, + const SCH_PLOT_SETTINGS& aPlotSettings ); + + /** + * Everything done, close the plot and restore the environment. + * + * @param aPlotter the plotter to close and destroy + * @param aOldsheetpath the stored old sheet path for the current sheet before the plot started + */ + void restoreEnvironment( PDF_PLOTTER* aPlotter, SCH_SHEET_PATH& aOldsheetpath ); + + + /** + * Create a file name with an absolute path name. + * + * @param aPlotFileName the name for the file to plot without a path. + * @param aExtension the extension for the file to plot. + * @param aReporter a point to a REPORTER object use to show messages (can be NULL). + * @return the created file name. + * @throw IO_ERROR on file I/O errors. + */ + wxFileName createPlotFileName( const SCH_PLOT_SETTINGS& aPlotSettings, + const wxString& aPlotFileName, const wxString& aExtension, + REPORTER* aReporter = nullptr ); + +private: + SCH_EDIT_FRAME* m_schFrame; + SCHEMATIC* m_schematic; + + COLOR_SETTINGS* m_colorSettings; + + wxString m_lastOutputFilePath; +}; + +#endif \ No newline at end of file diff --git a/eeschema/schematic.cpp b/eeschema/schematic.cpp index b8f859446e..0d968c9156 100644 --- a/eeschema/schematic.cpp +++ b/eeschema/schematic.cpp @@ -452,3 +452,19 @@ void SCHEMATIC::SetLegacySymbolInstanceData() screens.SetLegacySymbolInstanceData(); } + + +wxString SCHEMATIC::GetUniqueFilenameForCurrentSheet() +{ + // Filename is rootSheetName-sheetName-...-sheetName + // Note that we need to fetch the rootSheetName out of its filename, as the root SCH_SHEET's + // name is just a timestamp. + + wxFileName rootFn( CurrentSheet().at( 0 )->GetFileName() ); + wxString filename = rootFn.GetName(); + + for( unsigned i = 1; i < CurrentSheet().size(); i++ ) + filename += wxT( "-" ) + CurrentSheet().at( i )->GetName(); + + return filename; +} \ No newline at end of file diff --git a/eeschema/schematic.h b/eeschema/schematic.h index 52e424554f..b8dbbbd275 100644 --- a/eeschema/schematic.h +++ b/eeschema/schematic.h @@ -179,6 +179,15 @@ public: */ void SetLegacySymbolInstanceData(); + /** + * @return a filename that can be used in plot and print functions for the current screen + * and sheet path. This filename is unique and must be used instead of the screen filename + * when one must create files for each sheet in the hierarchy. + * Name is <root sheet filename>-<sheet path> and has no extension. + * However if filename is too long name is <sheet filename>-<sheet number> + */ + wxString GetUniqueFilenameForCurrentSheet(); + #if defined(DEBUG) void Show( int nestLevel, std::ostream& os ) const override {} #endif diff --git a/kicad/CMakeLists.txt b/kicad/CMakeLists.txt index 3919cfb117..561165b82d 100644 --- a/kicad/CMakeLists.txt +++ b/kicad/CMakeLists.txt @@ -25,6 +25,10 @@ set( KICAD_SRCS cli/command_export_pcb_svg.cpp cli/command_pcb.cpp cli/command_pcb_export.cpp + cli/command_export_sch_pdf.cpp + cli/command_export_sch_svg.cpp + cli/command_sch.cpp + cli/command_sch_export.cpp dialogs/dialog_template_selector_base.cpp dialogs/dialog_template_selector.cpp dialogs/panel_kicad_launcher_base.cpp diff --git a/kicad/cli/command_export_sch_pdf.cpp b/kicad/cli/command_export_sch_pdf.cpp new file mode 100644 index 0000000000..df91c0c552 --- /dev/null +++ b/kicad/cli/command_export_sch_pdf.cpp @@ -0,0 +1,78 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright (C) 1992-2022 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 "command_export_sch_pdf.h" +#include +#include "jobs/job_export_sch_pdf.h" +#include +#include +#include + +#include +#include + +#define ARG_EXCLUDE_DRAWING_SHEET "--exclude-drawing-sheet" +#define ARG_NO_BACKGROUND_COLOR "--no-background-color" + +CLI::EXPORT_SCH_PDF_COMMAND::EXPORT_SCH_PDF_COMMAND() : EXPORT_PCB_BASE_COMMAND( "pdf" ) +{ + m_argParser.add_argument( "-t", ARG_THEME ) + .default_value( std::string() ) + .help( "Color theme to use (will default to pcbnew settings)" ); + + m_argParser.add_argument( ARG_BLACKANDWHITE ) + .help( "Black and white only" ) + .implicit_value( true ) + .default_value( false ); + + m_argParser.add_argument( ARG_EXCLUDE_DRAWING_SHEET ) + .help( "No drawing sheet" ) + .implicit_value( true ) + .default_value( false ); + + m_argParser.add_argument( ARG_NO_BACKGROUND_COLOR ) + .help( "Avoid setting a background color (regardless of theme)" ) + .implicit_value( true ) + .default_value( false ); +} + + +int CLI::EXPORT_SCH_PDF_COMMAND::Perform( KIWAY& aKiway ) +{ + JOB_EXPORT_SCH_PDF* pdfJob = new JOB_EXPORT_SCH_PDF( true ); + + pdfJob->m_filename = FROM_UTF8( m_argParser.get( ARG_INPUT ).c_str() ); + pdfJob->m_outputFile = FROM_UTF8( m_argParser.get( ARG_OUTPUT ).c_str() ); + pdfJob->m_blackAndWhite = m_argParser.get( ARG_BLACKANDWHITE ); + pdfJob->m_plotDrawingSheet = !m_argParser.get( ARG_EXCLUDE_DRAWING_SHEET ); + pdfJob->m_useBackgroundColor = !m_argParser.get( ARG_NO_BACKGROUND_COLOR ); + + if( !wxFile::Exists( pdfJob->m_filename ) ) + { + wxFprintf( stderr, _( "Schematic file does not exist or is not accessible\n" ) ); + return EXIT_CODES::ERR_INVALID_INPUT_FILE; + } + + pdfJob->m_colorTheme = FROM_UTF8( m_argParser.get( ARG_THEME ).c_str() ); + + int exitCode = aKiway.ProcessJob( KIWAY::FACE_SCH, pdfJob ); + + return exitCode; +} \ No newline at end of file diff --git a/kicad/cli/command_export_sch_pdf.h b/kicad/cli/command_export_sch_pdf.h new file mode 100644 index 0000000000..30193908b8 --- /dev/null +++ b/kicad/cli/command_export_sch_pdf.h @@ -0,0 +1,37 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright (C) 1992-2022 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_SCH_PDF_H +#define COMMAND_EXPORT_SCH_PDF_H + +#include "command_export_pcb_base.h" + +namespace CLI +{ +class EXPORT_SCH_PDF_COMMAND : public EXPORT_PCB_BASE_COMMAND +{ +public: + EXPORT_SCH_PDF_COMMAND(); + + int Perform( KIWAY& aKiway ) override; +}; +} // namespace CLI + +#endif \ No newline at end of file diff --git a/kicad/cli/command_export_sch_svg.cpp b/kicad/cli/command_export_sch_svg.cpp new file mode 100644 index 0000000000..830f2be20b --- /dev/null +++ b/kicad/cli/command_export_sch_svg.cpp @@ -0,0 +1,78 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright (C) 1992-2022 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 "command_export_sch_svg.h" +#include +#include "jobs/job_export_sch_svg.h" +#include +#include +#include + +#include +#include + +#define ARG_EXCLUDE_DRAWING_SHEET "--exclude-drawing-sheet" +#define ARG_NO_BACKGROUND_COLOR "--no-background-color" + +CLI::EXPORT_SCH_SVG_COMMAND::EXPORT_SCH_SVG_COMMAND() : EXPORT_PCB_BASE_COMMAND( "svg" ) +{ + m_argParser.add_argument( "-t", ARG_THEME ) + .default_value( std::string() ) + .help( "Color theme to use (will default to pcbnew settings)" ); + + m_argParser.add_argument( ARG_BLACKANDWHITE ) + .help( "Black and white only" ) + .implicit_value( true ) + .default_value( false ); + + m_argParser.add_argument( ARG_EXCLUDE_DRAWING_SHEET ) + .help( "No drawing sheet" ) + .implicit_value( true ) + .default_value( false ); + + m_argParser.add_argument( ARG_NO_BACKGROUND_COLOR ) + .help( "Avoid setting a background color (regardless of theme)" ) + .implicit_value( true ) + .default_value( false ); +} + + +int CLI::EXPORT_SCH_SVG_COMMAND::Perform( KIWAY& aKiway ) +{ + JOB_EXPORT_SCH_SVG* pdfJob = new JOB_EXPORT_SCH_SVG( true ); + + pdfJob->m_filename = FROM_UTF8( m_argParser.get( ARG_INPUT ).c_str() ); + pdfJob->m_outputDirectory = FROM_UTF8( m_argParser.get( ARG_OUTPUT ).c_str() ); + pdfJob->m_blackAndWhite = m_argParser.get( ARG_BLACKANDWHITE ); + pdfJob->m_plotDrawingSheet = !m_argParser.get( ARG_EXCLUDE_DRAWING_SHEET ); + pdfJob->m_useBackgroundColor = !m_argParser.get( ARG_NO_BACKGROUND_COLOR ); + + if( !wxFile::Exists( pdfJob->m_filename ) ) + { + wxFprintf( stderr, _( "Schematic file does not exist or is not accessible\n" ) ); + return EXIT_CODES::ERR_INVALID_INPUT_FILE; + } + + pdfJob->m_colorTheme = FROM_UTF8( m_argParser.get( ARG_THEME ).c_str() ); + + int exitCode = aKiway.ProcessJob( KIWAY::FACE_SCH, pdfJob ); + + return exitCode; +} \ No newline at end of file diff --git a/kicad/cli/command_export_sch_svg.h b/kicad/cli/command_export_sch_svg.h new file mode 100644 index 0000000000..fc08e550e2 --- /dev/null +++ b/kicad/cli/command_export_sch_svg.h @@ -0,0 +1,37 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright (C) 1992-2022 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_SCH_SVG_H +#define COMMAND_EXPORT_SCH_SVG_H + +#include "command_export_pcb_base.h" + +namespace CLI +{ +class EXPORT_SCH_SVG_COMMAND : public EXPORT_PCB_BASE_COMMAND +{ +public: + EXPORT_SCH_SVG_COMMAND(); + + int Perform( KIWAY& aKiway ) override; +}; +} // namespace CLI + +#endif \ No newline at end of file diff --git a/kicad/cli/command_sch.cpp b/kicad/cli/command_sch.cpp new file mode 100644 index 0000000000..18ecf06f1d --- /dev/null +++ b/kicad/cli/command_sch.cpp @@ -0,0 +1,32 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright (C) 1992-2022 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 "command_sch.h" + +CLI::SCH_COMMAND::SCH_COMMAND() : COMMAND( "sch" ) +{ +} + +int CLI::SCH_COMMAND::Perform( KIWAY& aKiway ) +{ + std::cout << m_argParser; + + return 1; +} \ No newline at end of file diff --git a/kicad/cli/command_sch.h b/kicad/cli/command_sch.h new file mode 100644 index 0000000000..c0a564c3f9 --- /dev/null +++ b/kicad/cli/command_sch.h @@ -0,0 +1,36 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright (C) 1992-2022 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_SCH_H +#define COMMAND_SCH_H + +#include "command.h" + +namespace CLI +{ +struct SCH_COMMAND : public COMMAND +{ + SCH_COMMAND(); + + int Perform( KIWAY& aKiway ) override; +}; +} + +#endif \ No newline at end of file diff --git a/kicad/cli/command_sch_export.cpp b/kicad/cli/command_sch_export.cpp new file mode 100644 index 0000000000..fe0ded99f4 --- /dev/null +++ b/kicad/cli/command_sch_export.cpp @@ -0,0 +1,33 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright (C) 1992-2022 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 "command_sch_export.h" + +CLI::EXPORT_SCH_COMMAND::EXPORT_SCH_COMMAND() : COMMAND( "export" ) +{ +} + + +int CLI::EXPORT_SCH_COMMAND::Perform( KIWAY& aKiway ) +{ + std::cout << m_argParser; + + return 1; +} \ No newline at end of file diff --git a/kicad/cli/command_sch_export.h b/kicad/cli/command_sch_export.h new file mode 100644 index 0000000000..a9e099bfda --- /dev/null +++ b/kicad/cli/command_sch_export.h @@ -0,0 +1,36 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 Mark Roszko + * Copyright (C) 1992-2022 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_SCH_H +#define COMMAND_EXPORT_SCH_H + +#include "command.h" + +namespace CLI +{ +struct EXPORT_SCH_COMMAND : public COMMAND +{ + EXPORT_SCH_COMMAND(); + + int Perform( KIWAY& aKiway ) override; +}; +} + +#endif \ No newline at end of file diff --git a/kicad/kicad_cli.cpp b/kicad/kicad_cli.cpp index 7971783bd3..34a2a252f6 100644 --- a/kicad/kicad_cli.cpp +++ b/kicad/kicad_cli.cpp @@ -54,6 +54,10 @@ #include "cli/command_export_pcb_pdf.h" #include "cli/command_export_pcb_svg.h" #include "cli/command_export_pcb_step.h" +#include "cli/command_export_sch_pdf.h" +#include "cli/command_export_sch_svg.h" +#include "cli/command_sch.h" +#include "cli/command_sch_export.h" #include "cli/exit_codes.h" // a dummy to quiet linking with EDA_BASE_FRAME::config(); @@ -109,6 +113,10 @@ static CLI::EXPORT_PCB_PDF_COMMAND exportPcbPdfCmd{}; static CLI::EXPORT_PCB_GERBER_COMMAND exportPcbGerberCmd{}; static CLI::EXPORT_PCB_COMMAND exportPcbCmd{}; static CLI::PCB_COMMAND pcbCmd{}; +static CLI::EXPORT_SCH_COMMAND exportSchCmd{}; +static CLI::SCH_COMMAND schCmd{}; +static CLI::EXPORT_SCH_PDF_COMMAND exportSchPdfCmd{}; +static CLI::EXPORT_SCH_SVG_COMMAND exportSchSvgCmd{}; static std::vector commandStack = { { @@ -125,7 +133,18 @@ static std::vector commandStack = { } } } - } + }, + { + &schCmd, + { + { &exportSchCmd, + { + &exportSchPdfCmd, + &exportSchSvgCmd + } + } + } + }, };