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();
166
167 if( !plotFileName.IsOk() )
168 return;
169
170 if( !plotter->OpenFile( plotFileName.GetFullPath() ) )
171 {
172 if( aReporter )
173 {
174 msg.Printf( _( "Failed to create file '%s'." ),
175 plotFileName.GetFullPath() );
176 aReporter->Report( msg, RPT_SEVERITY_ERROR );
177 }
178 delete plotter;
179 return;
180 }
181
182 // Open the plotter and do the first page
183 setupPlotPagePDF( plotter, screen, aPlotOpts );
184
185 plotter->StartPlot( sheetList[i].GetPageNumber(), sheetName );
186 }
187 catch( const IO_ERROR& e )
188 {
189 // Cannot plot PDF file
190 if( aReporter )
191 {
192 msg.Printf( wxT( "PDF Plotter exception: %s" ), e.What() );
193 aReporter->Report( msg, RPT_SEVERITY_ERROR );
194 }
195
196 restoreEnvironment( plotter, oldsheetpath );
197 return;
198 }
199 }
200 else
201 {
202 /* For the following pages you need to close the (finished) page,
203 * reconfigure, and then start a new one */
204 plotter->ClosePage();
205 setupPlotPagePDF( plotter, screen, aPlotOpts );
206 SCH_SHEET_PATH parentSheet = sheetList[i];
207
208 if( parentSheet.size() > 1 )
209 {
210 // The sheet path is the full path to the sheet, so we need to remove the last
211 // sheet name to get the parent sheet path
212 parentSheet.pop_back();
213 }
214
215 wxString parentSheetName =
216 parentSheet.Last()->GetField( FIELD_T::SHEET_NAME )->GetShownText( false );
217
218 plotter->StartPage( sheetList[i].GetPageNumber(), sheetName,
219 parentSheet.GetPageNumber(), parentSheetName );
220 }
221
222 plotOneSheetPDF( plotter, screen, aPlotOpts );
223 }
224
225 // Everything done, close the plot and restore the environment
226 if( aReporter )
227 {
228 msg.Printf( _( "Plotted to '%s'.\n" ), plotFileName.GetFullPath() );
229 aReporter->Report( msg, RPT_SEVERITY_ACTION );
230 aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
231 }
232
233 restoreEnvironment( plotter, oldsheetpath );
234}
235
236
238 const SCH_PLOT_OPTS& aPlotOpts )
239{
240 if( aPlotOpts.m_useBackgroundColor && aPlotter->GetColorMode() )
241 {
242 aPlotter->SetColor( aPlotter->RenderSettings()->GetBackgroundColor() );
243
244 // Use page size selected in schematic to know the schematic bg area
245 const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic
246 VECTOR2I end( actualPage.GetWidthIU( schIUScale.IU_PER_MILS ),
247 actualPage.GetHeightIU( schIUScale.IU_PER_MILS ) );
248
249 aPlotter->Rect( VECTOR2I( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0 );
250 }
251
252 if( aPlotOpts.m_plotDrawingSheet )
253 {
254 COLOR4D color = COLOR4D::BLACK;
255
256 if( aPlotter->GetColorMode() )
258
259 wxString sheetName = m_schematic->CurrentSheet().Last()->GetName();
260 wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable();
261 const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic
262
263 SCHEMATIC* sch = aScreen->Schematic();
264 wxString variantName = sch->GetCurrentVariant();
265 wxString variantDesc = sch->GetVariantDescription( variantName );
266
267 PlotDrawingSheet( aPlotter, &sch->Project(), aScreen->GetTitleBlock(), actualPage, sch->GetProperties(),
268 aScreen->GetPageNumber(), aScreen->GetPageCount(), sheetName, sheetPath,
269 aScreen->GetFileName(), color, aScreen->GetVirtualPageNumber() == 1, variantName,
270 variantDesc );
271 }
272
273 aScreen->Plot( aPlotter, aPlotOpts );
274}
275
276
278 const SCH_PLOT_OPTS& aPlotOpts )
279{
280 PAGE_INFO plotPage; // page size selected to plot
281
282 // Considerations on page size and scaling requests
283 const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic
284
285 switch( aPlotOpts.m_pageSizeSelect )
286 {
287 case PAGE_SIZE_A:
288 plotPage.SetType( wxT( "A" ) );
289 plotPage.SetPortrait( actualPage.IsPortrait() );
290 break;
291
292 case PAGE_SIZE_A4:
293 plotPage.SetType( wxT( "A4" ) );
294 plotPage.SetPortrait( actualPage.IsPortrait() );
295 break;
296
297 case PAGE_SIZE_AUTO:
298 default:
299 plotPage = actualPage;
300 break;
301 }
302
303 double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils();
304 double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils();
305 double scale = std::min( scalex, scaley );
306 aPlotter->SetPageSettings( plotPage );
307
308 // Currently, plot units are in decimil
309 aPlotter->SetViewport( VECTOR2I( 0, 0 ), schIUScale.IU_PER_MILS / 10, scale, false );
310}
311
312
314 SCH_RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter )
315{
316 SCH_SHEET_PATH oldsheetpath = m_schematic->CurrentSheet(); // sheetpath is saved here
317 PAGE_INFO plotPage; // page size selected to plot
318 wxString msg;
319
320 /* When printing all pages, the printed page is not the current page.
321 * In complex hierarchies, we must update symbol references and other parameters in the
322 * given printed SCH_SCREEN, accordant to the sheet path because in complex hierarchies
323 * a SCH_SCREEN (a drawing ) is shared between many sheets and symbol references
324 * depend on the actual sheet path used.
325 */
326 SCH_SHEET_LIST sheetList;
327
328 if( aPlotOpts.m_plotAll )
329 {
330 sheetList.BuildSheetList( &m_schematic->Root(), true );
331 sheetList.SortByPageNumbers();
332
333 // remove the non-selected pages if we are in plot pages mode
334 if( aPlotOpts.m_plotPages.size() > 0 )
335 {
336 sheetList.TrimToPageNumbers( aPlotOpts.m_plotPages );
337 }
338 }
339 else
340 {
341 sheetList.push_back( m_schematic->CurrentSheet() );
342 }
343
344 for( unsigned i = 0; i < sheetList.size(); i++ )
345 {
346 m_schematic->SetCurrentSheet( sheetList[i] );
347 m_schematic->CurrentSheet().UpdateAllScreenReferences();
348 m_schematic->SetSheetNumberAndCount();
349
350 SCH_SCREEN* screen = m_schematic->CurrentSheet().LastScreen();
351 PAGE_INFO actualPage = screen->GetPageSettings();
352
353 switch( aPlotOpts.m_pageSizeSelect )
354 {
355 case PAGE_SIZE_A:
356 plotPage.SetType( wxT( "A" ) );
357 plotPage.SetPortrait( actualPage.IsPortrait() );
358 break;
359
360 case PAGE_SIZE_A4:
361 plotPage.SetType( wxT( "A4" ) );
362 plotPage.SetPortrait( actualPage.IsPortrait() );
363 break;
364
365 case PAGE_SIZE_AUTO:
366 default:
367 plotPage = actualPage;
368 break;
369 }
370
371 double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils();
372 double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils();
373 double scale = std::min( scalex, scaley );
374 VECTOR2I plot_offset;
375
376 try
377 {
378 wxString fname = m_schematic->GetUniqueFilenameForCurrentSheet();
379
380 // The sub sheet can be in a sub_hierarchy, but we plot the file in the
381 // main project folder (or the folder specified by the caller),
382 // so replace separators to create a unique filename:
383 fname.Replace( "/", "_" );
384 fname.Replace( "\\", "_" );
386 wxFileName plotFileName = createPlotFileName( aPlotOpts, fname, ext, aReporter );
387
388 m_lastOutputFilePath = plotFileName.GetFullPath();
390
391 if( !plotFileName.IsOk() )
392 {
393 if( aReporter )
394 {
395 // Error
396 msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() );
397 aReporter->Report( msg, RPT_SEVERITY_ERROR );
398 }
399 }
400 else if( plotOneSheetPS( plotFileName.GetFullPath(), screen, aRenderSettings,
401 actualPage, plot_offset, scale, aPlotOpts ) )
402 {
403 if( aReporter )
404 {
405 msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() );
406 aReporter->Report( msg, RPT_SEVERITY_ACTION );
407 }
408 }
409 else
410 {
411 if( aReporter )
412 {
413 // Error
414 msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() );
415 aReporter->Report( msg, RPT_SEVERITY_ERROR );
416 }
417 }
418 }
419 catch( IO_ERROR& e )
420 {
421 if( aReporter )
422 {
423 msg.Printf( wxT( "PS Plotter exception: %s" ), e.What() );
424 aReporter->Report( msg, RPT_SEVERITY_ERROR );
425 }
426 }
427 }
428
429 if( aReporter )
430 aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
431
432 restoreEnvironment( nullptr, oldsheetpath );
433}
434
435
436bool SCH_PLOTTER::plotOneSheetPS( const wxString& aFileName, SCH_SCREEN* aScreen,
437 RENDER_SETTINGS* aRenderSettings, const PAGE_INFO& aPageInfo,
438 const VECTOR2I& aPlot0ffset, double aScale,
439 const SCH_PLOT_OPTS& aPlotOpts )
440{
441 PS_PLOTTER* plotter = new PS_PLOTTER();
442 plotter->SetRenderSettings( aRenderSettings );
443 plotter->SetPageSettings( aPageInfo );
444 plotter->SetColorMode( !aPlotOpts.m_blackAndWhite );
445
446 // Currently, plot units are in decimil
447 plotter->SetViewport( aPlot0ffset, schIUScale.IU_PER_MILS / 10, aScale, false );
448
449 // Init :
450 plotter->SetCreator( wxT( "Eeschema-PS" ) );
451
452 if( !plotter->OpenFile( aFileName ) )
453 {
454 delete plotter;
455 return false;
456 }
457
458 plotter->StartPlot( m_schematic->CurrentSheet().GetPageNumber() );
459
460 if( aPlotOpts.m_useBackgroundColor && plotter->GetColorMode() )
461 {
463
464 // Use page size selected in schematic to know the schematic bg area
465 const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic
466 VECTOR2I end( actualPage.GetWidthIU( schIUScale.IU_PER_MILS ),
467 actualPage.GetHeightIU( schIUScale.IU_PER_MILS ) );
468
469 plotter->Rect( VECTOR2I( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0, 0 );
470 }
471
472 if( aPlotOpts.m_plotDrawingSheet )
473 {
474 wxString sheetName = m_schematic->CurrentSheet().Last()->GetName();
475 wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable();
477
478 SCHEMATIC* sch = aScreen->Schematic();
479 wxString variantName = sch->GetCurrentVariant();
480 wxString variantDesc = sch->GetVariantDescription( variantName );
481
482 PlotDrawingSheet( plotter, &sch->Project(), aScreen->GetTitleBlock(), aPageInfo, sch->GetProperties(),
483 aScreen->GetPageNumber(), aScreen->GetPageCount(), sheetName, sheetPath,
484 aScreen->GetFileName(), plotter->GetColorMode() ? color : COLOR4D::BLACK,
485 aScreen->GetVirtualPageNumber() == 1, variantName, variantDesc );
486 }
487
488 aScreen->Plot( plotter, aPlotOpts );
489
490 plotter->EndPlot();
491 delete plotter;
492
493 return true;
494}
495
496
498 SCH_RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter )
499{
500 wxString msg;
501 SCH_SHEET_PATH oldsheetpath = m_schematic->CurrentSheet();
502 SCH_SHEET_LIST sheetList;
503
504 if( aPlotOpts.m_plotAll )
505 {
506 sheetList.BuildSheetList( &m_schematic->Root(), true );
507 sheetList.SortByPageNumbers();
508
509 // remove the non-selected pages if we are in plot pages mode
510 if( aPlotOpts.m_plotPages.size() > 0 )
511 {
512 sheetList.TrimToPageNumbers( aPlotOpts.m_plotPages );
513 }
514 }
515 else
516 {
517 // in Eeschema, this prints the current page
518 sheetList.push_back( m_schematic->CurrentSheet() );
519 }
520
521 for( unsigned i = 0; i < sheetList.size(); i++ )
522 {
523 SCH_SCREEN* screen;
524
525 m_schematic->SetCurrentSheet( sheetList[i] );
526 m_schematic->CurrentSheet().UpdateAllScreenReferences();
527 m_schematic->SetSheetNumberAndCount();
528
529 screen = m_schematic->CurrentSheet().LastScreen();
530
531 try
532 {
533 wxString fname = m_schematic->GetUniqueFilenameForCurrentSheet();
534
535 // The sub sheet can be in a sub_hierarchy, but we plot the file in the
536 // main project folder (or the folder specified by the caller),
537 // so replace separators to create a unique filename:
538 fname.Replace( "/", "_" );
539 fname.Replace( "\\", "_" );
541 wxFileName plotFileName = createPlotFileName( aPlotOpts, fname, ext, aReporter );
542
543 m_lastOutputFilePath = plotFileName.GetFullPath();
545
546 if( !plotFileName.IsOk() )
547 return;
548
549 bool success = plotOneSheetSVG( plotFileName.GetFullPath(), screen, aRenderSettings,
550 aPlotOpts );
551
552 if( !success )
553 {
554 if( aReporter )
555 {
556 msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() );
557 aReporter->Report( msg, RPT_SEVERITY_ERROR );
558 }
559 }
560 else
561 {
562 if( aReporter )
563 {
564 msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() );
565 aReporter->Report( msg, RPT_SEVERITY_ACTION );
566 }
567 }
568 }
569 catch( const IO_ERROR& e )
570 {
571 if( aReporter )
572 {
573 // Cannot plot SVG file
574 msg.Printf( wxT( "SVG Plotter exception: %s" ), e.What() );
575 aReporter->Report( msg, RPT_SEVERITY_ERROR );
576 }
577 break;
578 }
579 }
580
581 if( aReporter )
582 {
583 aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
584 }
585
586 restoreEnvironment( nullptr, oldsheetpath );
587}
588
589
590bool SCH_PLOTTER::plotOneSheetSVG( const wxString& aFileName, SCH_SCREEN* aScreen,
591 RENDER_SETTINGS* aRenderSettings,
592 const SCH_PLOT_OPTS& aPlotOpts )
593{
594 PAGE_INFO plotPage;
595
596 // Adjust page size and scaling requests
597 const PAGE_INFO& actualPage = aScreen->GetPageSettings(); // page size selected in schematic
598
599 switch( aPlotOpts.m_pageSizeSelect )
600 {
601 case PAGE_SIZE_A:
602 plotPage.SetType( wxT( "A" ) );
603 plotPage.SetPortrait( actualPage.IsPortrait() );
604 break;
605
606 case PAGE_SIZE_A4:
607 plotPage.SetType( wxT( "A4" ) );
608 plotPage.SetPortrait( actualPage.IsPortrait() );
609 break;
610
611 case PAGE_SIZE_AUTO:
612 default:
613 plotPage = actualPage;
614 break;
615 }
616
617 SVG_PLOTTER* plotter = new SVG_PLOTTER();
618 plotter->SetRenderSettings( aRenderSettings );
619 plotter->SetPageSettings( plotPage );
620 plotter->SetColorMode( aPlotOpts.m_blackAndWhite ? false : true );
621 VECTOR2I plot_offset;
622
623 double scalex = (double) plotPage.GetWidthMils() / actualPage.GetWidthMils();
624 double scaley = (double) plotPage.GetHeightMils() / actualPage.GetHeightMils();
625 double scale = std::min( scalex, scaley );
626
627 // Currently, plot units are in decimil
628 plotter->SetViewport( plot_offset, schIUScale.IU_PER_MILS / 10, scale, false );
629
630 // Init :
631 plotter->SetCreator( wxT( "Eeschema-SVG" ) );
632
633 if( !plotter->OpenFile( aFileName ) )
634 {
635 delete plotter;
636 return false;
637 }
638
639 plotter->StartPlot( m_schematic->CurrentSheet().GetPageNumber() );
640
641 if( aPlotOpts.m_useBackgroundColor && plotter->GetColorMode() )
642 {
644
645 // Use page size selected in schematic to know the schematic bg area
646 VECTOR2I end( actualPage.GetWidthIU( schIUScale.IU_PER_MILS ),
647 actualPage.GetHeightIU( schIUScale.IU_PER_MILS ) );
648
649 plotter->Rect( VECTOR2I( 0, 0 ), end, FILL_T::FILLED_SHAPE, 1.0, 0 );
650 }
651
652 if( aPlotOpts.m_plotDrawingSheet )
653 {
654 wxString sheetName = m_schematic->CurrentSheet().Last()->GetName();
655 wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable();
657
658 SCHEMATIC* sch = aScreen->Schematic();
659 wxString variantName = sch->GetCurrentVariant();
660 wxString variantDesc = sch->GetVariantDescription( variantName );
661
662 PlotDrawingSheet( plotter, &sch->Project(), aScreen->GetTitleBlock(), actualPage, sch->GetProperties(),
663 aScreen->GetPageNumber(), aScreen->GetPageCount(), sheetName, sheetPath,
664 aScreen->GetFileName(), plotter->GetColorMode() ? color : COLOR4D::BLACK,
665 aScreen->GetVirtualPageNumber() == 1, variantName, variantDesc );
666 }
667
668 aScreen->Plot( plotter, aPlotOpts );
669
670 plotter->EndPlot();
671 delete plotter;
672
673 return true;
674}
675
676
678 SCH_RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter )
679{
680 SCH_SHEET_PATH oldsheetpath = m_schematic->CurrentSheet();
681
682 /* When printing all pages, the printed page is not the current page. In complex hierarchies,
683 * we must update symbol references and other parameters in the given printed SCH_SCREEN,
684 * according to the sheet path because in complex hierarchies a SCH_SCREEN (a drawing ) is
685 * shared between many sheets and symbol references depend on the actual sheet path used.
686 */
687 SCH_SHEET_LIST sheetList;
688
689 if( aPlotOpts.m_plotAll )
690 {
691 sheetList.BuildSheetList( &m_schematic->Root(), true );
692 sheetList.SortByPageNumbers();
693
694 // remove the non-selected pages if we are in plot pages mode
695 if( aPlotOpts.m_plotPages.size() > 0 )
696 sheetList.TrimToPageNumbers( aPlotOpts.m_plotPages );
697 }
698 else
699 {
700 // in Eeschema, this prints the current page
701 sheetList.push_back( m_schematic->CurrentSheet() );
702 }
703
704 for( unsigned i = 0; i < sheetList.size(); i++ )
705 {
706 m_schematic->SetCurrentSheet( sheetList[i] );
707 m_schematic->CurrentSheet().UpdateAllScreenReferences();
708 m_schematic->SetSheetNumberAndCount();
709
710 SCH_SCREEN* screen = m_schematic->CurrentSheet().LastScreen();
711 VECTOR2I plot_offset;
712 wxString msg;
713
714 try
715 {
716 wxString fname = m_schematic->GetUniqueFilenameForCurrentSheet();
717
718 // The sub sheet can be in a sub_hierarchy, but we plot the file in the
719 // main project folder (or the folder specified by the caller),
720 // so replace separators to create a unique filename:
721 fname.Replace( "/", "_" );
722 fname.Replace( "\\", "_" );
724 wxFileName plotFileName = createPlotFileName( aPlotOpts, fname, ext, aReporter );
725
726 m_lastOutputFilePath = plotFileName.GetFullPath();
728
729 if( !plotFileName.IsOk() )
730 return;
731
732 if( plotOneSheetDXF( plotFileName.GetFullPath(), screen, aRenderSettings, plot_offset,
733 1.0, aPlotOpts ) )
734 {
735 if( aReporter )
736 {
737 msg.Printf( _( "Plotted to '%s'." ), plotFileName.GetFullPath() );
738 aReporter->Report( msg, RPT_SEVERITY_ACTION );
739 }
740 }
741 else // Error
742 {
743 if( aReporter )
744 {
745 msg.Printf( _( "Failed to create file '%s'." ), plotFileName.GetFullPath() );
746 aReporter->Report( msg, RPT_SEVERITY_ERROR );
747 }
748 }
749 }
750 catch( IO_ERROR& e )
751 {
752 if( aReporter )
753 {
754 msg.Printf( wxT( "DXF Plotter exception: %s" ), e.What() );
755 aReporter->Report( msg, RPT_SEVERITY_ERROR );
756 }
757
758 m_schematic->SetCurrentSheet( oldsheetpath );
759 m_schematic->CurrentSheet().UpdateAllScreenReferences();
760 m_schematic->SetSheetNumberAndCount();
761 return;
762 }
763 }
764
765 if( aReporter )
766 aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
767
768 restoreEnvironment( nullptr, oldsheetpath );
769}
770
771
772bool SCH_PLOTTER::plotOneSheetDXF( const wxString& aFileName, SCH_SCREEN* aScreen,
773 RENDER_SETTINGS* aRenderSettings, const VECTOR2I& aPlotOffset,
774 double aScale, const SCH_PLOT_OPTS& aPlotOpts )
775{
776 aRenderSettings->LoadColors( m_colorSettings );
777 aRenderSettings->SetDefaultPenWidth( 0 );
778
779 const PAGE_INFO& pageInfo = aScreen->GetPageSettings();
780 DXF_PLOTTER* plotter = new DXF_PLOTTER();
781
782 plotter->SetUnits( aPlotOpts.m_DXF_File_Unit );
783
784 plotter->SetRenderSettings( aRenderSettings );
785 plotter->SetPageSettings( pageInfo );
786 plotter->SetColorMode( !aPlotOpts.m_blackAndWhite );
787
788 // Currently, plot units are in decimil
789 plotter->SetViewport( aPlotOffset, schIUScale.IU_PER_MILS / 10, aScale, false );
790
791 // Init :
792 plotter->SetCreator( wxT( "Eeschema-DXF" ) );
793
794 if( !plotter->OpenFile( aFileName ) )
795 {
796 delete plotter;
797 return false;
798 }
799
800 plotter->StartPlot( m_schematic->CurrentSheet().GetPageNumber() );
801
802 if( aPlotOpts.m_plotDrawingSheet )
803 {
804 wxString sheetName = m_schematic->CurrentSheet().Last()->GetName();
805 wxString sheetPath = m_schematic->CurrentSheet().PathHumanReadable();
807
808 wxString variantName = m_schematic->GetCurrentVariant();
809 wxString variantDesc = m_schematic->GetVariantDescription( variantName );
810
811 PlotDrawingSheet( plotter, &m_schematic->Project(), aScreen->GetTitleBlock(), pageInfo,
812 m_schematic->GetProperties(), aScreen->GetPageNumber(), aScreen->GetPageCount(), sheetName,
813 sheetPath, aScreen->GetFileName(), plotter->GetColorMode() ? color : COLOR4D::BLACK,
814 aScreen->GetVirtualPageNumber() == 1, variantName, variantDesc );
815 }
816
817 aScreen->Plot( plotter, aPlotOpts );
818
819 // finish
820 plotter->EndPlot();
821 delete plotter;
822
823 return true;
824}
825
826
828{
829 if( aPlotter )
830 {
831 aPlotter->EndPlot();
832 delete aPlotter;
833 }
834
835 // Restore the initial sheet
836 m_schematic->SetCurrentSheet( aOldsheetpath );
837 m_schematic->CurrentSheet().UpdateAllScreenReferences();
838 m_schematic->SetSheetNumberAndCount();
839}
840
841
843 const wxString& aPlotFileName,
844 const wxString& aExtension, REPORTER* aReporter )
845{
846 wxFileName retv;
847 wxFileName tmp;
848
849 tmp.SetPath( aPlotOpts.m_outputDirectory );
850 retv.SetPath( tmp.GetPath() );
851
852 if( !aPlotFileName.IsEmpty() )
853 retv.SetName( aPlotFileName );
854 else
855 retv.SetName( _( "Schematic" ) );
856
857 retv.SetExt( aExtension );
858
859 if( !EnsureFileDirectoryExists( &tmp, retv.GetFullName(), aReporter ) || !tmp.IsDirWritable() )
860 {
861 if( aReporter )
862 {
863 wxString msg = wxString::Format( _( "Failed to write plot files to folder '%s'." ),
864 tmp.GetPath() );
865 aReporter->Report( msg, RPT_SEVERITY_ERROR );
866 }
867
868 retv.Clear();
869
870 SCHEMATIC_SETTINGS& settings = m_schematic->Settings();
871 settings.m_PlotDirectoryName.Clear();
872 }
873 else
874 {
875 retv.SetPath( tmp.GetPath() );
876 }
877
878 wxLogTrace( tracePathsAndFiles, "Writing plot file '%s'.", retv.GetFullPath() );
879
880 return retv;
881}
882
883
884void SCH_PLOTTER::Plot( PLOT_FORMAT aPlotFormat, const SCH_PLOT_OPTS& aPlotOpts,
885 SCH_RENDER_SETTINGS* aRenderSettings, REPORTER* aReporter )
886{
887 m_outputFilePaths.clear();
888
889 wxString oldVariant = m_schematic->GetCurrentVariant();
890 m_schematic->SetCurrentVariant( aPlotOpts.m_variant );
892
893 switch( aPlotFormat )
894 {
895 default:
896 case PLOT_FORMAT::POST: createPSFiles( aPlotOpts, aRenderSettings, aReporter ); break;
897 case PLOT_FORMAT::DXF: createDXFFiles( aPlotOpts, aRenderSettings, aReporter ); break;
898 case PLOT_FORMAT::PDF: createPDFFile( aPlotOpts, aRenderSettings, aReporter ); break;
899 case PLOT_FORMAT::SVG: createSVGFiles( aPlotOpts, aRenderSettings, aReporter ); break;
900 case PLOT_FORMAT::HPGL: /* no longer supported */ break;
901 }
902
903 m_schematic->SetCurrentVariant( oldVariant );
904}
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:406
static wxString GetDefaultFileExtension()
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:105
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:136
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Definition plotter.cpp:77
virtual void SetAuthor(const wxString &aAuthor)
Definition plotter.h:190
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition plotter.h:169
void SetRenderSettings(RENDER_SETTINGS *aSettings)
Definition plotter.h:166
virtual void SetTitle(const wxString &aTitle)
Definition plotter.h:189
RENDER_SETTINGS * RenderSettings()
Definition plotter.h:167
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:188
bool GetColorMode() const
Definition plotter.h:164
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:163
virtual void SetSubject(const wxString &aSubject)
Definition plotter.h:191
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:89
wxString GetVariantDescription(const wxString &aVariantName) const
Return the description for a variant.
PROJECT & Project() const
Return a reference to the project this schematic is part of.
Definition schematic.h:104
wxString GetCurrentVariant() const
Return the current variant being edited.
const std::map< wxString, wxString > * GetProperties()
Definition schematic.h:107
Schematic editor (Eeschema) main window.
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0, const wxString &aVariantName=wxEmptyString) 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.
std::vector< wxString > m_outputFilePaths
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:141
const wxString & GetFileName() const
Definition sch_screen.h:154
SCHEMATIC * Schematic() const
const TITLE_BLOCK & GetTitleBlock() const
Definition sch_screen.h:165
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:62
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:579
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, const wxString &aVariantName, const wxString &aVariantDesc)
#define _(s)
@ FILLED_SHAPE
Fill with object color.
Definition eda_shape.h:60
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition layer_ids.h:498
@ LAYER_SCHEMATIC_BACKGROUND
Definition layer_ids.h:490
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:74
wxString m_outputDirectory
Definition sch_plotter.h:69
wxString m_outputFile
Definition sch_plotter.h:70
bool m_blackAndWhite
Definition sch_plotter.h:61
wxString m_variant
Definition sch_plotter.h:71
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:687