KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_plotter.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 1992-2018 Jean-Pierre Charras jp.charras at wanadoo.fr
5 * Copyright (C) 1992-2010 Lorenzo Marcantonio
6 * Copyright (C) 2011 Wayne Stambaugh <[email protected]>
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <wx/log.h>
28#include <common.h>
29#include <sch_plotter.h>
32
33#include <pgm_base.h>
34#include <trace_helpers.h>
35
36#include <sch_edit_frame.h>
37#include <sch_painter.h>
38#include <schematic.h>
39#include <sch_screen.h>
41
42// Note:
43// We need to switch between sheets to plot a hierarchy and update references and sheet number
44// Use SCHEMATIC::SetCurrentSheet( xxx ) to switch to a sheet.
45// Do not use SCH_EDIT_FRAME::SetCurrentSheet( xxx ) to switch to a sheet, because the new sheet
46// is not displayed, but SCH_EDIT_FRAME::SetCurrentSheet() has side effects to the current VIEW
47// (clear some data used to show the sheet on screen) and does not fully restore the "old" screen
48
49
51 m_schematic( aSchematic )
52{
53 m_colorSettings = nullptr;
54}
55
56
58 m_schematic( &aFrame->Schematic() )
59{
60 m_colorSettings = nullptr;
61}
62
63
65 REPORTER* aReporter, const wxString& aExt )
66{
67 if( !aPlotOpts.m_outputFile.empty() )
68 {
69 return aPlotOpts.m_outputFile;
70 }
71 else
72 {
73 wxString fname = m_schematic->GetUniqueFilenameForCurrentSheet();
74
75 // The sub sheet can be in a sub_hierarchy, but we plot the file in the main
76 // project folder (or the folder specified by the caller), so replace separators
77 // to create a unique filename:
78 fname.Replace( "/", "_" );
79 fname.Replace( "\\", "_" );
80
81 return createPlotFileName( aPlotOpts, fname, aExt, aReporter );
82 }
83
84}
85
86
88 SCH_RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter )
89{
90 SCH_SHEET_PATH oldsheetpath = m_schematic->CurrentSheet(); // sheetpath is saved here
91
92 /* When printing all pages, the printed page is not the current page. In complex hierarchies,
93 * we must update symbol references and other parameters in the given printed SCH_SCREEN,
94 * according to the sheet path because in complex hierarchies a SCH_SCREEN (a drawing ) is
95 * shared between many sheets and symbol references depend on the actual sheet path used.
96 */
97 SCH_SHEET_LIST sheetList;
98
99 if( aPlotOpts.m_plotAll || aPlotOpts.m_plotPages.size() > 0 )
100 {
101 sheetList.BuildSheetList( &m_schematic->Root(), true );
103
104 // remove the non-selected pages if we are in plot pages mode
105 if( aPlotOpts.m_plotPages.size() > 0 )
106 sheetList.TrimToPageNumbers( aPlotOpts.m_plotPages );
107 }
108 else
109 {
110 // in Eeschema, this prints the current page
111 sheetList.push_back( m_schematic->CurrentSheet() );
112 }
113
114 if( sheetList.empty() )
115 {
116 if( aReporter )
117 aReporter->Report( _( "No sheets to plot." ), RPT_SEVERITY_ERROR );
118
119 return;
120 }
121
122 wxCHECK( m_schematic, /* void */ );
123
124 // Allocate the plotter and set the job level parameter
125 PDF_PLOTTER* plotter = new PDF_PLOTTER( &m_schematic->Project() );
126 plotter->SetRenderSettings( aRenderSettings );
127 plotter->SetColorMode( !aPlotOpts.m_blackAndWhite );
128 plotter->SetCreator( wxT( "Eeschema-PDF" ) );
129 plotter->SetTitle( ExpandTextVars( m_schematic->RootScreen()->GetTitleBlock().GetTitle(),
130 &m_schematic->Project() ) );
131
132 wxString msg;
133 wxFileName plotFileName;
134
135 for( unsigned i = 0; i < sheetList.size(); i++ )
136 {
137 m_schematic->SetCurrentSheet( sheetList[i] );
138 m_schematic->CurrentSheet().UpdateAllScreenReferences();
139 m_schematic->SetSheetNumberAndCount();
140
141 SCH_SCREEN* screen = m_schematic->CurrentSheet().LastScreen();
142 wxString sheetName = sheetList[i].Last()->GetField( FIELD_T::SHEET_NAME )->GetShownText( false );
143
144 if( aPlotOpts.m_PDFMetadata )
145 {
146 msg = wxS( "AUTHOR" );
147
148 if( m_schematic->ResolveTextVar( &sheetList[i], &msg, 0 ) )
149 plotter->SetAuthor( msg );
150
151 msg = wxS( "SUBJECT" );
152
153 if( m_schematic->ResolveTextVar( &sheetList[i], &msg, 0 ) )
154 plotter->SetSubject( msg );
155 }
156
157 if( i == 0 )
158 {
159 try
160 {
162 plotFileName = getOutputFilenameSingle( aPlotOpts, aReporter, ext );
163
164 m_lastOutputFilePath = plotFileName.GetFullPath();
165
166 if( !plotFileName.IsOk() )
167 return;
168
169 if( !plotter->OpenFile( plotFileName.GetFullPath() ) )
170 {
171 if( aReporter )
172 {
173 msg.Printf( _( "Failed to create file '%s'." ),
174 plotFileName.GetFullPath() );
175 aReporter->Report( msg, RPT_SEVERITY_ERROR );
176 }
177 delete plotter;
178 return;
179 }
180
181 // Open the plotter and do the first page
182 setupPlotPagePDF( plotter, screen, aPlotOpts );
183
184 plotter->StartPlot( sheetList[i].GetPageNumber(), sheetName );
185 }
186 catch( const IO_ERROR& e )
187 {
188 // Cannot plot PDF file
189 if( aReporter )
190 {
191 msg.Printf( wxT( "PDF Plotter exception: %s" ), e.What() );
192 aReporter->Report( msg, RPT_SEVERITY_ERROR );
193 }
194
195 restoreEnvironment( plotter, oldsheetpath );
196 return;
197 }
198 }
199 else
200 {
201 /* For the following pages you need to close the (finished) page,
202 * reconfigure, and then start a new one */
203 plotter->ClosePage();
204 setupPlotPagePDF( plotter, screen, aPlotOpts );
205 SCH_SHEET_PATH parentSheet = sheetList[i];
206
207 if( parentSheet.size() > 1 )
208 {
209 // The sheet path is the full path to the sheet, so we need to remove the last
210 // sheet name to get the parent sheet path
211 parentSheet.pop_back();
212 }
213
214 wxString parentSheetName =
215 parentSheet.Last()->GetField( FIELD_T::SHEET_NAME )->GetShownText( false );
216
217 plotter->StartPage( sheetList[i].GetPageNumber(), sheetName,
218 parentSheet.GetPageNumber(), parentSheetName );
219 }
220
221 plotOneSheetPDF( plotter, screen, aPlotOpts );
222 }
223
224 // Everything done, close the plot and restore the environment
225 if( aReporter )
226 {
227 msg.Printf( _( "Plotted to '%s'.\n" ), plotFileName.GetFullPath() );
228 aReporter->Report( msg, RPT_SEVERITY_ACTION );
229 aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
230 }
231
232 restoreEnvironment( plotter, oldsheetpath );
233}
234
235
237 const SCH_PLOT_OPTS& aPlotOpts )
238{
239 if( aPlotOpts.m_useBackgroundColor && aPlotter->GetColorMode() )
240 {
241 aPlotter->SetColor( aPlotter->RenderSettings()->GetBackgroundColor() );
242
243 // Use page size selected in schematic to know the schematic bg area
244 const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic
245 VECTOR2I end( actualPage.GetWidthIU( schIUScale.IU_PER_MILS ),
246 actualPage.GetHeightIU( schIUScale.IU_PER_MILS ) );
247
248 aPlotter->Rect( VECTOR2I( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 );
249 }
250
251 if( aPlotOpts.m_plotDrawingSheet )
252 {
254
255 if( aPlotter->GetColorMode() )
257
258 wxString sheetName = m_schematic->CurrentSheet().Last()->GetName();
259 wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable();
260 const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic
261
262 PlotDrawingSheet( aPlotter, &aScreen->Schematic()->Project(),
263 aScreen->GetTitleBlock(),
264 actualPage,
265 aScreen->Schematic()->GetProperties(),
266 aScreen->GetPageNumber(), aScreen->GetPageCount(), sheetName, sheetPath,
267 aScreen->GetFileName(), color, aScreen->GetVirtualPageNumber() == 1 );
268 }
269
270 aScreen->Plot( aPlotter, aPlotOpts );
271}
272
273
275 const SCH_PLOT_OPTS& aPlotOpts )
276{
277 PAGE_INFO plotPage; // page size selected to plot
278
279 // Considerations on page size and scaling requests
280 const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic
281
282 switch( aPlotOpts.m_pageSizeSelect )
283 {
284 case PAGE_SIZE_A:
285 plotPage.SetType( wxT( "A" ) );
286 plotPage.SetPortrait( actualPage.IsPortrait() );
287 break;
288
289 case PAGE_SIZE_A4:
290 plotPage.SetType( wxT( "A4" ) );
291 plotPage.SetPortrait( actualPage.IsPortrait() );
292 break;
293
294 case PAGE_SIZE_AUTO:
295 default:
296 plotPage = actualPage;
297 break;
298 }
299
300 double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils();
301 double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils();
302 double scale = std::min( scalex, scaley );
303 aPlotter->SetPageSettings( plotPage );
304
305 // Currently, plot units are in decimil
306 aPlotter->SetViewport( VECTOR2I( 0, 0 ), schIUScale.IU_PER_MILS / 10, scale, false );
307}
308
309
311 SCH_RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter )
312{
313 SCH_SHEET_PATH oldsheetpath = m_schematic->CurrentSheet(); // sheetpath is saved here
314 PAGE_INFO plotPage; // page size selected to plot
315 wxString msg;
316
317 /* When printing all pages, the printed page is not the current page.
318 * In complex hierarchies, we must update symbol references and other parameters in the
319 * given printed SCH_SCREEN, accordant to the sheet path because in complex hierarchies
320 * a SCH_SCREEN (a drawing ) is shared between many sheets and symbol references
321 * depend on the actual sheet path used.
322 */
323 SCH_SHEET_LIST sheetList;
324
325 if( aPlotOpts.m_plotAll )
326 {
327 sheetList.BuildSheetList( &m_schematic->Root(), true );
328 sheetList.SortByPageNumbers();
329
330 // remove the non-selected pages if we are in plot pages mode
331 if( aPlotOpts.m_plotPages.size() > 0 )
332 {
333 sheetList.TrimToPageNumbers( aPlotOpts.m_plotPages );
334 }
335 }
336 else
337 {
338 sheetList.push_back( m_schematic->CurrentSheet() );
339 }
340
341 for( unsigned i = 0; i < sheetList.size(); i++ )
342 {
343 m_schematic->SetCurrentSheet( sheetList[i] );
344 m_schematic->CurrentSheet().UpdateAllScreenReferences();
345 m_schematic->SetSheetNumberAndCount();
346
347 SCH_SCREEN* screen = m_schematic->CurrentSheet().LastScreen();
348 PAGE_INFO actualPage = screen->GetPageSettings();
349
350 switch( aPlotOpts.m_pageSizeSelect )
351 {
352 case PAGE_SIZE_A:
353 plotPage.SetType( wxT( "A" ) );
354 plotPage.SetPortrait( actualPage.IsPortrait() );
355 break;
356
357 case PAGE_SIZE_A4:
358 plotPage.SetType( wxT( "A4" ) );
359 plotPage.SetPortrait( actualPage.IsPortrait() );
360 break;
361
362 case PAGE_SIZE_AUTO:
363 default:
364 plotPage = actualPage;
365 break;
366 }
367
368 double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils();
369 double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils();
370 double scale = std::min( scalex, scaley );
371 VECTOR2I plot_offset;
372
373 try
374 {
375 wxString fname = m_schematic->GetUniqueFilenameForCurrentSheet();
376
377 // The sub sheet can be in a sub_hierarchy, but we plot the file in the
378 // main project folder (or the folder specified by the caller),
379 // so replace separators to create a unique filename:
380 fname.Replace( "/", "_" );
381 fname.Replace( "\\", "_" );
383 wxFileName plotFileName = createPlotFileName( aPlotOpts, fname, ext, aReporter );
384
385 m_lastOutputFilePath = plotFileName.GetFullPath();
386
387 if( !plotFileName.IsOk() )
388 {
389 if( aReporter )
390 {
391 // Error
392 msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() );
393 aReporter->Report( msg, RPT_SEVERITY_ERROR );
394 }
395 }
396 else if( plotOneSheetPS( plotFileName.GetFullPath(), screen, aRenderSettings,
397 actualPage, plot_offset, scale, aPlotOpts ) )
398 {
399 if( aReporter )
400 {
401 msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() );
402 aReporter->Report( msg, RPT_SEVERITY_ACTION );
403 }
404 }
405 else
406 {
407 if( aReporter )
408 {
409 // Error
410 msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() );
411 aReporter->Report( msg, RPT_SEVERITY_ERROR );
412 }
413 }
414 }
415 catch( IO_ERROR& e )
416 {
417 if( aReporter )
418 {
419 msg.Printf( wxT( "PS Plotter exception: %s" ), e.What() );
420 aReporter->Report( msg, RPT_SEVERITY_ERROR );
421 }
422 }
423 }
424
425 if( aReporter )
426 aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
427
428 restoreEnvironment( nullptr, oldsheetpath );
429}
430
431
432bool SCH_PLOTTER::plotOneSheetPS( const wxString& aFileName, SCH_SCREEN* aScreen,
433 RENDER_SETTINGS* aRenderSettings, const PAGE_INFO& aPageInfo,
434 const VECTOR2I& aPlot0ffset, double aScale,
435 const SCH_PLOT_OPTS& aPlotOpts )
436{
437 PS_PLOTTER* plotter = new PS_PLOTTER();
438 plotter->SetRenderSettings( aRenderSettings );
439 plotter->SetPageSettings( aPageInfo );
440 plotter->SetColorMode( !aPlotOpts.m_blackAndWhite );
441
442 // Currently, plot units are in decimil
443 plotter->SetViewport( aPlot0ffset, schIUScale.IU_PER_MILS / 10, aScale, false );
444
445 // Init :
446 plotter->SetCreator( wxT( "Eeschema-PS" ) );
447
448 if( !plotter->OpenFile( aFileName ) )
449 {
450 delete plotter;
451 return false;
452 }
453
454 plotter->StartPlot( m_schematic->CurrentSheet().GetPageNumber() );
455
456 if( aPlotOpts.m_useBackgroundColor && plotter->GetColorMode() )
457 {
459
460 // Use page size selected in schematic to know the schematic bg area
461 const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic
462 VECTOR2I end( actualPage.GetWidthIU( schIUScale.IU_PER_MILS ),
463 actualPage.GetHeightIU( schIUScale.IU_PER_MILS ) );
464
465 plotter->Rect( VECTOR2I( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0, 0 );
466 }
467
468 if( aPlotOpts.m_plotDrawingSheet )
469 {
470 wxString sheetName = m_schematic->CurrentSheet().Last()->GetName();
471 wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable();
473
474 PlotDrawingSheet( plotter, &aScreen->Schematic()->Project(),
475 aScreen->GetTitleBlock(),
476 aPageInfo, aScreen->Schematic()->GetProperties(),
477 aScreen->GetPageNumber(), aScreen->GetPageCount(), sheetName, sheetPath,
478 aScreen->GetFileName(), plotter->GetColorMode() ? color : COLOR4D::BLACK,
479 aScreen->GetVirtualPageNumber() == 1 );
480 }
481
482 aScreen->Plot( plotter, aPlotOpts );
483
484 plotter->EndPlot();
485 delete plotter;
486
487 return true;
488}
489
490
492 SCH_RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter )
493{
494 wxString msg;
495 SCH_SHEET_PATH oldsheetpath = m_schematic->CurrentSheet();
496 SCH_SHEET_LIST sheetList;
497
498 if( aPlotOpts.m_plotAll )
499 {
500 sheetList.BuildSheetList( &m_schematic->Root(), true );
501 sheetList.SortByPageNumbers();
502
503 // remove the non-selected pages if we are in plot pages mode
504 if( aPlotOpts.m_plotPages.size() > 0 )
505 {
506 sheetList.TrimToPageNumbers( aPlotOpts.m_plotPages );
507 }
508 }
509 else
510 {
511 // in Eeschema, this prints the current page
512 sheetList.push_back( m_schematic->CurrentSheet() );
513 }
514
515 for( unsigned i = 0; i < sheetList.size(); i++ )
516 {
517 SCH_SCREEN* screen;
518
519 m_schematic->SetCurrentSheet( sheetList[i] );
520 m_schematic->CurrentSheet().UpdateAllScreenReferences();
521 m_schematic->SetSheetNumberAndCount();
522
523 screen = m_schematic->CurrentSheet().LastScreen();
524
525 try
526 {
527 wxString fname = m_schematic->GetUniqueFilenameForCurrentSheet();
528
529 // The sub sheet can be in a sub_hierarchy, but we plot the file in the
530 // main project folder (or the folder specified by the caller),
531 // so replace separators to create a unique filename:
532 fname.Replace( "/", "_" );
533 fname.Replace( "\\", "_" );
535 wxFileName plotFileName = createPlotFileName( aPlotOpts, fname, ext, aReporter );
536
537 m_lastOutputFilePath = plotFileName.GetFullPath();
538
539 if( !plotFileName.IsOk() )
540 return;
541
542 bool success = plotOneSheetSVG( plotFileName.GetFullPath(), screen, aRenderSettings,
543 aPlotOpts );
544
545 if( !success )
546 {
547 if( aReporter )
548 {
549 msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() );
550 aReporter->Report( msg, RPT_SEVERITY_ERROR );
551 }
552 }
553 else
554 {
555 if( aReporter )
556 {
557 msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() );
558 aReporter->Report( msg, RPT_SEVERITY_ACTION );
559 }
560 }
561 }
562 catch( const IO_ERROR& e )
563 {
564 if( aReporter )
565 {
566 // Cannot plot SVG file
567 msg.Printf( wxT( "SVG Plotter exception: %s" ), e.What() );
568 aReporter->Report( msg, RPT_SEVERITY_ERROR );
569 }
570 break;
571 }
572 }
573
574 if( aReporter )
575 {
576 aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
577 }
578
579 restoreEnvironment( nullptr, oldsheetpath );
580}
581
582
583bool SCH_PLOTTER::plotOneSheetSVG( const wxString& aFileName, SCH_SCREEN* aScreen,
584 RENDER_SETTINGS* aRenderSettings,
585 const SCH_PLOT_OPTS& aPlotOpts )
586{
587 PAGE_INFO plotPage;
588
589 // Adjust page size and scaling requests
590 const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic
591
592 switch( aPlotOpts.m_pageSizeSelect )
593 {
594 case PAGE_SIZE_A:
595 plotPage.SetType( wxT( "A" ) );
596 plotPage.SetPortrait( actualPage.IsPortrait() );
597 break;
598
599 case PAGE_SIZE_A4:
600 plotPage.SetType( wxT( "A4" ) );
601 plotPage.SetPortrait( actualPage.IsPortrait() );
602 break;
603
604 case PAGE_SIZE_AUTO:
605 default:
606 plotPage = actualPage;
607 break;
608 }
609
610 SVG_PLOTTER* plotter = new SVG_PLOTTER();
611 plotter->SetRenderSettings( aRenderSettings );
612 plotter->SetPageSettings( plotPage );
613 plotter->SetColorMode( aPlotOpts.m_blackAndWhite ? false : true );
614 VECTOR2I plot_offset;
615
616 double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils();
617 double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils();
618 double scale = std::min( scalex, scaley );
619
620 // Currently, plot units are in decimil
621 plotter->SetViewport( plot_offset, schIUScale.IU_PER_MILS / 10, scale, false );
622
623 // Init :
624 plotter->SetCreator( wxT( "Eeschema-SVG" ) );
625
626 if( !plotter->OpenFile( aFileName ) )
627 {
628 delete plotter;
629 return false;
630 }
631
632 plotter->StartPlot( m_schematic->CurrentSheet().GetPageNumber() );
633
634 if( aPlotOpts.m_useBackgroundColor && plotter->GetColorMode() )
635 {
637
638 // Use page size selected in schematic to know the schematic bg area
639 VECTOR2I end( actualPage.GetWidthIU( schIUScale.IU_PER_MILS ),
640 actualPage.GetHeightIU( schIUScale.IU_PER_MILS ) );
641
642 plotter->Rect( VECTOR2I( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0, 0 );
643 }
644
645 if( aPlotOpts.m_plotDrawingSheet )
646 {
647 wxString sheetName = m_schematic->CurrentSheet().Last()->GetName();
648 wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable();
650
651 PlotDrawingSheet( plotter, &aScreen->Schematic()->Project(),
652 aScreen->GetTitleBlock(),
653 actualPage, aScreen->Schematic()->GetProperties(),
654 aScreen->GetPageNumber(),
655 aScreen->GetPageCount(), sheetName, sheetPath, aScreen->GetFileName(),
656 plotter->GetColorMode() ? color : COLOR4D::BLACK,
657 aScreen->GetVirtualPageNumber() == 1 );
658 }
659
660 aScreen->Plot( plotter, aPlotOpts );
661
662 plotter->EndPlot();
663 delete plotter;
664
665 return true;
666}
667
668
670 SCH_RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter )
671{
672 SCH_SHEET_PATH oldsheetpath = m_schematic->CurrentSheet();
673
674 /* When printing all pages, the printed page is not the current page. In complex hierarchies,
675 * we must update symbol references and other parameters in the given printed SCH_SCREEN,
676 * according to the sheet path because in complex hierarchies a SCH_SCREEN (a drawing ) is
677 * shared between many sheets and symbol references depend on the actual sheet path used.
678 */
679 SCH_SHEET_LIST sheetList;
680
681 if( aPlotOpts.m_plotAll )
682 {
683 sheetList.BuildSheetList( &m_schematic->Root(), true );
684 sheetList.SortByPageNumbers();
685
686 // remove the non-selected pages if we are in plot pages mode
687 if( aPlotOpts.m_plotPages.size() > 0 )
688 sheetList.TrimToPageNumbers( aPlotOpts.m_plotPages );
689 }
690 else
691 {
692 // in Eeschema, this prints the current page
693 sheetList.push_back( m_schematic->CurrentSheet() );
694 }
695
696 for( unsigned i = 0; i < sheetList.size(); i++ )
697 {
698 m_schematic->SetCurrentSheet( sheetList[i] );
699 m_schematic->CurrentSheet().UpdateAllScreenReferences();
700 m_schematic->SetSheetNumberAndCount();
701
702 SCH_SCREEN* screen = m_schematic->CurrentSheet().LastScreen();
703 VECTOR2I plot_offset;
704 wxString msg;
705
706 try
707 {
708 wxString fname = m_schematic->GetUniqueFilenameForCurrentSheet();
709
710 // The sub sheet can be in a sub_hierarchy, but we plot the file in the
711 // main project folder (or the folder specified by the caller),
712 // so replace separators to create a unique filename:
713 fname.Replace( "/", "_" );
714 fname.Replace( "\\", "_" );
716 wxFileName plotFileName = createPlotFileName( aPlotOpts, fname, ext, aReporter );
717
718 m_lastOutputFilePath = plotFileName.GetFullPath();
719
720 if( !plotFileName.IsOk() )
721 return;
722
723 if( plotOneSheetDXF( plotFileName.GetFullPath(), screen, aRenderSettings, plot_offset,
724 1.0, aPlotOpts ) )
725 {
726 if( aReporter )
727 {
728 msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() );
729 aReporter->Report( msg, RPT_SEVERITY_ACTION );
730 }
731 }
732 else // Error
733 {
734 if( aReporter )
735 {
736 msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() );
737 aReporter->Report( msg, RPT_SEVERITY_ERROR );
738 }
739 }
740 }
741 catch( IO_ERROR& e )
742 {
743 if( aReporter )
744 {
745 msg.Printf( wxT( "DXF Plotter exception: %s" ), e.What() );
746 aReporter->Report( msg, RPT_SEVERITY_ERROR );
747 }
748
749 m_schematic->SetCurrentSheet( oldsheetpath );
750 m_schematic->CurrentSheet().UpdateAllScreenReferences();
751 m_schematic->SetSheetNumberAndCount();
752 return;
753 }
754 }
755
756 if( aReporter )
757 aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
758
759 restoreEnvironment( nullptr, oldsheetpath );
760}
761
762
763bool SCH_PLOTTER::plotOneSheetDXF( const wxString& aFileName, SCH_SCREEN* aScreen,
764 RENDER_SETTINGS* aRenderSettings, const VECTOR2I& aPlotOffset,
765 double aScale, const SCH_PLOT_OPTS& aPlotOpts )
766{
767 aRenderSettings->LoadColors( m_colorSettings );
768 aRenderSettings->SetDefaultPenWidth( 0 );
769
770 const PAGE_INFO& pageInfo = aScreen->GetPageSettings();
771 DXF_PLOTTER* plotter = new DXF_PLOTTER();
772
773 plotter->SetUnits( aPlotOpts.m_DXF_File_Unit );
774
775 plotter->SetRenderSettings( aRenderSettings );
776 plotter->SetPageSettings( pageInfo );
777 plotter->SetColorMode( !aPlotOpts.m_blackAndWhite );
778
779 // Currently, plot units are in decimil
780 plotter->SetViewport( aPlotOffset, schIUScale.IU_PER_MILS / 10, aScale, false );
781
782 // Init :
783 plotter->SetCreator( wxT( "Eeschema-DXF" ) );
784
785 if( !plotter->OpenFile( aFileName ) )
786 {
787 delete plotter;
788 return false;
789 }
790
791 plotter->StartPlot( m_schematic->CurrentSheet().GetPageNumber() );
792
793 if( aPlotOpts.m_plotDrawingSheet )
794 {
795 wxString sheetName = m_schematic->CurrentSheet().Last()->GetName();
796 wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable();
798
799 PlotDrawingSheet( plotter, &m_schematic->Project(),
800 aScreen->GetTitleBlock(),
801 pageInfo,
802 aScreen->Schematic()->GetProperties(), aScreen->GetPageNumber(),
803 aScreen->GetPageCount(), sheetName, sheetPath, aScreen->GetFileName(),
804 plotter->GetColorMode() ? color : COLOR4D::BLACK,
805 aScreen->GetVirtualPageNumber() == 1 );
806 }
807
808 aScreen->Plot( plotter, aPlotOpts );
809
810 // finish
811 plotter->EndPlot();
812 delete plotter;
813
814 return true;
815}
816
817
819{
820 if( aPlotter )
821 {
822 aPlotter->EndPlot();
823 delete aPlotter;
824 }
825
826 // Restore the initial sheet
827 m_schematic->SetCurrentSheet( aOldsheetpath );
828 m_schematic->CurrentSheet().UpdateAllScreenReferences();
829 m_schematic->SetSheetNumberAndCount();
830}
831
832
834 const wxString& aPlotFileName,
835 const wxString& aExtension, REPORTER* aReporter )
836{
837 wxFileName retv;
838 wxFileName tmp;
839
840 tmp.SetPath( aPlotOpts.m_outputDirectory );
841 retv.SetPath( tmp.GetPath() );
842
843 if( !aPlotFileName.IsEmpty() )
844 retv.SetName( aPlotFileName );
845 else
846 retv.SetName( _( "Schematic" ) );
847
848 retv.SetExt( aExtension );
849
850 if( !EnsureFileDirectoryExists( &tmp, retv.GetFullName(), aReporter ) || !tmp.IsDirWritable() )
851 {
852 if( aReporter )
853 {
854 wxString msg = wxString::Format( _( "Failed to write plot files to folder '%s'." ),
855 tmp.GetPath() );
856 aReporter->Report( msg, RPT_SEVERITY_ERROR );
857 }
858
859 retv.Clear();
860
861 SCHEMATIC_SETTINGS& settings = m_schematic->Settings();
862 settings.m_PlotDirectoryName.Clear();
863 }
864 else
865 {
866 retv.SetPath( tmp.GetPath() );
867 }
868
869 wxLogTrace( tracePathsAndFiles, "Writing plot file '%s'.", retv.GetFullPath() );
870
871 return retv;
872}
873
874
875void SCH_PLOTTER::Plot( PLOT_FORMAT aPlotFormat, const SCH_PLOT_OPTS& aPlotOpts,
876 SCH_RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter )
877{
879
880 switch( aPlotFormat )
881 {
882 default:
883 case PLOT_FORMAT::POST: createPSFiles( aPlotOpts, aRenderSettings, aReporter ); break;
884 case PLOT_FORMAT::DXF: createDXFFiles( aPlotOpts, aRenderSettings, aReporter ); break;
885 case PLOT_FORMAT::PDF: createPDFFile( aPlotOpts, aRenderSettings, aReporter ); break;
886 case PLOT_FORMAT::SVG: createSVGFiles( aPlotOpts, aRenderSettings, aReporter ); break;
887 case PLOT_FORMAT::HPGL: /* no longer supported */ break;
888 }
889}
int color
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:114
int GetPageCount() const
Definition base_screen.h:72
int GetVirtualPageNumber() const
Definition base_screen.h:75
const wxString & GetPageNumber() const
static const COLOR4D BLACK
Definition color4d.h:402
static wxString GetDefaultFileExtension()
Definition plotter_dxf.h:42
void SetUnits(DXF_UNITS aUnit)
Set the units to use for plotting the DXF file.
virtual void SetViewport(const VECTOR2I &aOffset, double aIusPerDecimil, double aScale, bool aMirror) override
Set the scale/position for the DXF plot.
virtual bool StartPlot(const wxString &aPageNumber) override
Open the DXF plot with a skeleton header.
virtual bool EndPlot() override
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:104
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
void SetDefaultPenWidth(int aWidth)
virtual void LoadColors(const COLOR_SETTINGS *aSettings)
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
virtual const COLOR4D & GetBackgroundColor() const =0
Return current background color settings.
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition page_info.h:79
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
int GetHeightIU(double aIUScale) const
Gets the page height in IU.
Definition page_info.h:168
bool SetType(PAGE_SIZE_TYPE aPageSize, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
double GetHeightMils() const
Definition page_info.h:147
int GetWidthIU(double aIUScale) const
Gets the page width in IU.
Definition page_info.h:159
double GetWidthMils() const
Definition page_info.h:142
bool IsPortrait() const
Definition page_info.h:128
virtual void ClosePage()
Close the current page in the PDF document (and emit its compressed stream).
virtual bool EndPlot() override
virtual bool OpenFile(const wxString &aFullFilename) override
Open or create the plot file aFullFilename.
virtual bool StartPlot(const wxString &aPageNumber) override
The PDF engine supports multiple pages; the first one is opened 'for free' the following are to be cl...
static wxString GetDefaultFileExtension()
virtual void StartPage(const wxString &aPageNumber, const wxString &aPageName=wxEmptyString, const wxString &aParentPageNumber=wxEmptyString, const wxString &aParentPageName=wxEmptyString)
Start a new page in the PDF document.
Base plotter engine class.
Definition plotter.h:121
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Definition plotter.cpp:76
virtual void SetAuthor(const wxString &aAuthor)
Definition plotter.h:175
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition plotter.h:154
void SetRenderSettings(RENDER_SETTINGS *aSettings)
Definition plotter.h:151
virtual void SetTitle(const wxString &aTitle)
Definition plotter.h:174
RENDER_SETTINGS * RenderSettings()
Definition plotter.h:152
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width, int aCornerRadius=0)=0
virtual void SetCreator(const wxString &aCreator)
Definition plotter.h:173
bool GetColorMode() const
Definition plotter.h:149
virtual void SetViewport(const VECTOR2I &aOffset, double aIusPerDecimil, double aScale, bool aMirror)=0
Set the plot offset and scaling for the current plot.
virtual void SetColorMode(bool aColorMode)
Plot in B/W or color.
Definition plotter.h:148
virtual void SetSubject(const wxString &aSubject)
Definition plotter.h:176
virtual void SetColor(const COLOR4D &color)=0
virtual void SetColor(const COLOR4D &color) override
The SetColor implementation is split with the subclasses: the PSLIKE computes the rgb values,...
virtual bool EndPlot() override
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width, int aCornerRadius=0) override
virtual void SetViewport(const VECTOR2I &aOffset, double aIusPerDecimil, double aScale, bool aMirror) override
Set the plot offset and scaling for the current plot.
virtual bool StartPlot(const wxString &aPageNumber) override
The code within this function (and the CloseFilePS function) creates postscript files whose contents ...
static wxString GetDefaultFileExtension()
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition reporter.h:102
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the end of the list, for objects that support report ordering.
Definition reporter.h:112
These are loaded from Eeschema settings but then overwritten by the project settings.
Holds all the data relating to one schematic.
Definition schematic.h:88
PROJECT & Project() const
Return a reference to the project this schematic is part of.
Definition schematic.h:103
const std::map< wxString, wxString > * GetProperties()
Definition schematic.h:106
Schematic editor (Eeschema) main window.
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0) const
void Plot(PLOT_FORMAT aPlotFormat, const SCH_PLOT_OPTS &aPlotOpts, SCH_RENDER_SETTINGS *aRenderSettings, REPORTER *aReporter=nullptr)
Perform the plotting of the schematic using the given aPlotFormat and a\ aPlotSettings.
wxFileName getOutputFilenameSingle(const SCH_PLOT_OPTS &aPlotOpts, REPORTER *aReporter, const wxString &ext)
Return the output filename for formats where the output is a single file.
void createSVGFiles(const SCH_PLOT_OPTS &aPlotOpts, SCH_RENDER_SETTINGS *aRenderSettings, REPORTER *aReporter)
void createPSFiles(const SCH_PLOT_OPTS &aPlotOpts, SCH_RENDER_SETTINGS *aRenderSettings, REPORTER *aReporter)
void plotOneSheetPDF(PLOTTER *aPlotter, SCH_SCREEN *aScreen, const SCH_PLOT_OPTS &aPlotOpts)
wxFileName createPlotFileName(const SCH_PLOT_OPTS &aPlotOpts, const wxString &aPlotFileName, const wxString &aExtension, REPORTER *aReporter=nullptr)
Create a file name with an absolute path name.
SCH_PLOTTER(SCH_EDIT_FRAME *aFrame)
Constructor for usage with a frame having the schematic we want to print loaded.
bool plotOneSheetDXF(const wxString &aFileName, SCH_SCREEN *aScreen, RENDER_SETTINGS *aRenderSettings, const VECTOR2I &aPlotOffset, double aScale, const SCH_PLOT_OPTS &aPlotOpts)
void createDXFFiles(const SCH_PLOT_OPTS &aPlotOpts, SCH_RENDER_SETTINGS *aRenderSettings, REPORTER *aReporter)
wxString m_lastOutputFilePath
void restoreEnvironment(PDF_PLOTTER *aPlotter, SCH_SHEET_PATH &aOldsheetpath)
Everything done, close the plot and restore the environment.
bool plotOneSheetSVG(const wxString &aFileName, SCH_SCREEN *aScreen, RENDER_SETTINGS *aRenderSettings, const SCH_PLOT_OPTS &aPlotOpts)
void setupPlotPagePDF(PLOTTER *aPlotter, SCH_SCREEN *aScreen, const SCH_PLOT_OPTS &aPlotOpts)
void createPDFFile(const SCH_PLOT_OPTS &aPlotOpts, SCH_RENDER_SETTINGS *aRenderSettings, REPORTER *aReporter)
COLOR_SETTINGS * m_colorSettings
bool plotOneSheetPS(const wxString &aFileName, SCH_SCREEN *aScreen, RENDER_SETTINGS *aRenderSettings, const PAGE_INFO &aPageInfo, const VECTOR2I &aPlot0ffset, double aScale, const SCH_PLOT_OPTS &aPlotOpts)
SCHEMATIC * m_schematic
const PAGE_INFO & GetPageSettings() const
Definition sch_screen.h:139
const wxString & GetFileName() const
Definition sch_screen.h:152
SCHEMATIC * Schematic() const
const TITLE_BLOCK & GetTitleBlock() const
Definition sch_screen.h:163
void Plot(PLOTTER *aPlotter, const SCH_PLOT_OPTS &aPlotOpts) const
Plot all the schematic objects to aPlotter.
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void TrimToPageNumbers(const std::vector< wxString > &aPageInclusions)
Truncates the list by removing sheet's with page numbers not in the given list.
void SortByPageNumbers(bool aUpdateVirtualPageNums=true)
Sort the list of sheets by page number.
void SortByHierarchicalPageNumbers(bool aUpdateVirtualPageNums=true)
This works like SortByPageNumbers, but it sorts the sheets first by their hierarchical depth and then...
void BuildSheetList(SCH_SHEET *aSheet, bool aCheckIntegrity)
Build the list of sheets and their sheet path from aSheet.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
wxString GetPageNumber() const
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
size_t size() const
Forwarded method from std::vector.
void pop_back()
Forwarded method from std::vector.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
virtual bool StartPlot(const wxString &aPageNumber) override
Create SVG file header.
virtual void SetViewport(const VECTOR2I &aOffset, double aIusPerDecimil, double aScale, bool aMirror) override
Set the plot offset and scaling for the current plot.
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width, int aCornerRadius=0) override
virtual bool EndPlot() override
static wxString GetDefaultFileExtension()
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition common.cpp:59
bool EnsureFileDirectoryExists(wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter)
Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist.
Definition common.cpp:376
The common library.
void PlotDrawingSheet(PLOTTER *plotter, const PROJECT *aProject, const TITLE_BLOCK &aTitleBlock, const PAGE_INFO &aPageInfo, const std::map< wxString, wxString > *aProperties, const wxString &aSheetNumber, int aSheetCount, const wxString &aSheetName, const wxString &aSheetPath, const wxString &aFilename, COLOR4D aColor, bool aIsFirstPage)
#define _(s)
@ FILLED_SHAPE
Fill with object color.
Definition eda_shape.h:58
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition layer_ids.h:494
@ LAYER_SCHEMATIC_BACKGROUND
Definition layer_ids.h:487
see class PGM_BASE
PLOT_FORMAT
The set of supported output plot formats.
Definition plotter.h:64
Plotting engines similar to ps (PostScript, Gerber, svg)
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
@ PAGE_SIZE_AUTO
Definition sch_plotter.h:48
@ PAGE_SIZE_A
Definition sch_plotter.h:50
@ PAGE_SIZE_A4
Definition sch_plotter.h:49
COLOR_SETTINGS * GetColorSettings(const wxString &aName)
const int scale
std::vector< wxString > m_plotPages
Definition sch_plotter.h:58
wxString m_theme
Definition sch_plotter.h:67
DXF_UNITS m_DXF_File_Unit
Definition sch_plotter.h:72
wxString m_outputDirectory
Definition sch_plotter.h:69
wxString m_outputFile
Definition sch_plotter.h:70
bool m_blackAndWhite
Definition sch_plotter.h:61
bool m_useBackgroundColor
Definition sch_plotter.h:63
bool m_plotDrawingSheet
Definition sch_plotter.h:57
VECTOR2I end
wxLogTrace helper definitions.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695