KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_plot.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include "dialog_plot.h"
21
22#include <wx/bmpbuttn.h>
23#include <wx/clntdata.h>
24#include <wx/dirdlg.h>
25#include <wx/msgdlg.h>
26#include <wx/rearrangectrl.h>
27
28#include <plotters/plotter.h>
29#include <confirm.h>
30#include <pcb_edit_frame.h>
32#include <pcbplot.h>
33#include <pgm_base.h>
35#include <reporter.h>
37#include <layer_ids.h>
38#include <bitmaps.h>
39#include <dialog_gendrill.h>
40#include <string_utils.h>
44#include <tool/tool_manager.h>
46#include <tools/drc_tool.h>
47#include <math/util.h> // for KiROUND
48#include <macros.h>
57#include <pcb_plotter.h>
58
59
61
62
63static double selectionToScale( int selection )
64{
65 switch( selection )
66 {
67 default: return 1.0;
68 case 0: return 0.0;
69 case 2: return 1.5;
70 case 3: return 2.0;
71 case 4: return 3.0;
72 }
73}
74
75
79class PCB_LAYER_ID_CLIENT_DATA : public wxClientData
80{
81public:
85
87 m_id( aId )
88 { }
89
90 void SetData( PCB_LAYER_ID aId ) { m_id = aId; }
91 PCB_LAYER_ID Layer() const { return m_id; }
92
93private:
95};
96
97
98PCB_LAYER_ID_CLIENT_DATA* getLayerClientData( const wxRearrangeList* aList, int aIdx )
99{
100 return static_cast<PCB_LAYER_ID_CLIENT_DATA*>( aList->GetClientObject( aIdx ) );
101}
102
103
105 : DIALOG_PLOT( aEditFrame, aEditFrame )
106{
107}
108
109
110DIALOG_PLOT::DIALOG_PLOT( PCB_EDIT_FRAME* aEditFrame, wxWindow* aParent, JOB_EXPORT_PCB_PLOT* aJob ) :
111 DIALOG_PLOT_BASE( aParent ),
112 m_editFrame( aEditFrame ),
114 m_job( aJob )
115{
116 BOARD* board = m_editFrame->GetBoard();
117
119
120 SetName( DLG_WINDOW_NAME );
122
123 if( m_job )
124 {
125 SetTitle( aJob->GetSettingsDialogTitle() );
126
128 m_messagesPanel->Hide();
129
130 m_browseButton->Hide();
131 m_openDirButton->Hide();
132 m_staticTextPlotFmt->Hide();
133 m_plotFormatOpt->Hide();
134 m_buttonDRC->Hide();
136 m_sdbSizer1Apply->Hide();
137 m_zoneFillCheck->SetLabel( _( "Refill zones before plotting" ) );
138
139 // UpdateUI rather than wxEVT_CHECKBOX so dialog undo/redo also refreshes the label
140 m_staticTextDir->Bind( wxEVT_UPDATE_UI,
141 [this]( wxUpdateUIEvent& aEvent )
142 {
144 aEvent.Skip();
145 } );
146 }
147 else
148 {
149 m_plotOpts = m_editFrame->GetPlotSettings();
150 m_messagesPanel->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
151 }
152
153 // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
154 // non-job versions.
155 m_hash_key = TO_UTF8( GetTitle() );
156
157 m_variantChoiceCtrl->Append( board->GetVariantNamesForUI() );
158 m_variantChoiceCtrl->SetSelection( 0 );
159
160 int order = 0;
161 wxArrayInt plotAllLayersOrder;
162 wxArrayString plotAllLayersChoicesStrings;
163 std::vector<PCB_LAYER_ID> layersIdChoiceList;
164 int textWidth = 0;
165
166 for( PCB_LAYER_ID layer : board->GetEnabledLayers().SeqStackupForPlotting() )
167 {
168 wxString layerName = board->GetLayerName( layer );
169
170 // wxCOL_WIDTH_AUTOSIZE doesn't work on all platforms, so we calculate width here
171 textWidth = std::max( textWidth, KIUI::GetTextSize( layerName, m_layerCheckListBox ).x );
172
173 plotAllLayersChoicesStrings.Add( layerName );
174 layersIdChoiceList.push_back( layer );
175
176 if( alg::contains( m_plotOpts.GetPlotOnAllLayersSequence(), layer ) )
177 plotAllLayersOrder.push_back( order );
178 else
179 plotAllLayersOrder.push_back( ~order );
180
181 order += 1;
182 }
183
184 int checkColSize = 22;
185 int layerColSize = textWidth + 15;
186
187#ifdef __WXMAC__
188 // TODO: something in wxWidgets 3.1.x pads checkbox columns with extra space. (It used to
189 // also be that the width of the column would get set too wide (to 30), but that's patched in
190 // our local wxWidgets fork.)
191 checkColSize += 30;
192#endif
193
194 m_layerCheckListBox->SetMinClientSize( wxSize( checkColSize + layerColSize,
195 m_layerCheckListBox->GetMinClientSize().y ) );
196
197 wxStaticBox* allLayersLabel = new wxStaticBox( this, wxID_ANY, _( "Plot on All Layers" ) );
198 wxStaticBoxSizer* sbSizer = new wxStaticBoxSizer( allLayersLabel, wxVERTICAL );
199
200 m_plotAllLayersList = new wxRearrangeList( sbSizer->GetStaticBox(), wxID_ANY,
201 wxDefaultPosition, wxDefaultSize,
202 plotAllLayersOrder, plotAllLayersChoicesStrings, 0 );
203
204 m_plotAllLayersList->SetMinClientSize( wxSize( checkColSize + layerColSize,
205 m_plotAllLayersList->GetMinClientSize().y ) );
206
207 // Attach the LAYER_ID to each item in m_plotAllLayersList
208 // plotAllLayersChoicesStrings and layersIdChoiceList are in the same order,
209 // but m_plotAllLayersList has these strings in a different order
210 for( size_t idx = 0; idx < layersIdChoiceList.size(); idx++ )
211 {
212 wxString& txt = plotAllLayersChoicesStrings[idx];
213 int list_idx = m_plotAllLayersList->FindString( txt, true );
214
215 PCB_LAYER_ID layer_id = layersIdChoiceList[idx];
216 m_plotAllLayersList->SetClientObject( list_idx, new PCB_LAYER_ID_CLIENT_DATA( layer_id ) );
217 }
218
219 sbSizer->Add( m_plotAllLayersList, 1, wxALL | wxEXPAND | wxFIXED_MINSIZE, 3 );
220
221 wxBoxSizer* bButtonSizer;
222 bButtonSizer = new wxBoxSizer( wxHORIZONTAL );
223
224 m_bpMoveUp = new STD_BITMAP_BUTTON( sbSizer->GetStaticBox(), wxID_ANY, wxNullBitmap,
225 wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW | 0 );
226 m_bpMoveUp->SetToolTip( _( "Move current selection up" ) );
228
229 bButtonSizer->Add( m_bpMoveUp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 3 );
230
231 m_bpMoveDown = new STD_BITMAP_BUTTON( sbSizer->GetStaticBox(), wxID_ANY, wxNullBitmap,
232 wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW | 0 );
233 m_bpMoveDown->SetToolTip( _( "Move current selection down" ) );
235
236 bButtonSizer->Add( m_bpMoveDown, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5 );
237
238 sbSizer->Add( bButtonSizer, 0, wxALL | wxEXPAND, 3 );
239
240 bmiddleSizer->Insert( 1, sbSizer, 1, wxALL | wxEXPAND, 5 );
241
244
245 if( m_job )
246 {
248 }
249 else
250 {
251 SetupStandardButtons( { { wxID_OK, _( "Plot" ) },
252 { wxID_APPLY, _( "Generate Drill Files..." ) },
253 { wxID_CANCEL, _( "Close" ) } } );
254 }
255
256 GetSizer()->Fit( this );
257 GetSizer()->SetSizeHints( this );
258
259 m_bpMoveUp->Bind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_PLOT::onPlotAllListMoveUp, this );
260 m_bpMoveDown->Bind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_PLOT::onPlotAllListMoveDown, this );
261
262 m_layerCheckListBox->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( DIALOG_PLOT::OnRightClickLayers ),
263 nullptr, this );
264
265 m_plotAllLayersList->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( DIALOG_PLOT::OnRightClickAllLayers ),
266 nullptr, this );
267}
268
269
271{
272 s_lastAllLayersOrder.clear();
273
274 for( int ii = 0; ii < (int) m_plotAllLayersList->GetCount(); ++ii )
276
277 m_bpMoveDown->Unbind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_PLOT::onPlotAllListMoveDown, this );
278 m_bpMoveUp->Unbind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_PLOT::onPlotAllListMoveUp, this );
279}
280
281
283{
284 BOARD* board = m_editFrame->GetBoard();
285 wxFileName fileName;
286
287 PROJECT_FILE& projectFile = m_editFrame->Prj().GetProjectFile();
288
289 // Could devote a PlotOrder() function in place of UIOrder().
291
292 // Select the current board variant in the variant choice
293 if( m_job )
294 {
295 if( !m_job->m_variant.IsEmpty() )
296 {
297 int idx = m_variantChoiceCtrl->FindString( m_job->m_variant );
298
299 if( idx != wxNOT_FOUND )
300 m_variantChoiceCtrl->SetSelection( idx );
301 }
302 }
303 else
304 {
305 wxString currentVariant = board->GetCurrentVariant();
306
307 if( !currentVariant.IsEmpty() )
308 {
309 int idx = m_variantChoiceCtrl->FindString( currentVariant );
310
311 if( idx != wxNOT_FOUND )
312 m_variantChoiceCtrl->SetSelection( idx );
313 }
314 }
315
316 if( !m_job && !projectFile.m_PcbLastPath[ LAST_PATH_PLOT ].IsEmpty() )
317 m_plotOpts.SetOutputDirectory( projectFile.m_PcbLastPath[ LAST_PATH_PLOT ] );
318
319 if( m_job
320 && !( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::POST
321 && static_cast<JOB_EXPORT_PCB_PS*>( m_job )->m_useGlobalSettings ) )
322 {
323 // When we are using a job we get the PS adjust values from the plot options
324 // The exception is when this is a fresh job and we want to get the global values as defaults
326 m_plotOpts.GetFineScaleAdjustX() ) );
327
329 m_plotOpts.GetFineScaleAdjustY() ) );
330 m_trackWidthCorrection.SetValue( m_plotOpts.GetWidthAdjust() );
331 m_zoneFillCheck->SetValue( m_job->m_checkZonesBeforePlot );
332 }
333
334 // The reasonable width correction value must be in a range of
335 // [-(MinTrackWidth-1), +(MinClearanceValue-1)] decimils.
336 m_widthAdjustMinValue = -( board->GetDesignSettings().m_TrackMinWidth - 1 );
338
339 switch( m_plotOpts.GetFormat() )
340 {
341 default:
342 case PLOT_FORMAT::GERBER: m_plotFormatOpt->SetSelection( 0 ); break;
343 case PLOT_FORMAT::POST: m_plotFormatOpt->SetSelection( 1 ); break;
344 case PLOT_FORMAT::SVG: m_plotFormatOpt->SetSelection( 2 ); break;
345 case PLOT_FORMAT::DXF: m_plotFormatOpt->SetSelection( 3 ); break;
346 case PLOT_FORMAT::HPGL: /* no longer supported */ break;
347 case PLOT_FORMAT::PDF: m_plotFormatOpt->SetSelection( 4 ); break;
348 case PLOT_FORMAT::PNG: m_plotFormatOpt->SetSelection( 5 ); break;
349 }
350
351 m_plotPSNegativeOpt->SetValue( m_plotOpts.GetNegative() );
352 m_forcePSA4OutputOpt->SetValue( m_plotOpts.GetA4Output() );
353
354 // Populate the check list box by all enabled layers names.
355 for( PCB_LAYER_ID layer : m_layerList )
356 {
357 int checkIndex = m_layerCheckListBox->Append( board->GetLayerName( layer ) );
358
359 if( m_plotOpts.GetLayerSelection()[layer] )
360 m_layerCheckListBox->Check( checkIndex );
361 }
362
364
365 // Option for disabling Gerber Aperture Macro (for broken Gerber readers)
366 m_disableApertMacros->SetValue( m_plotOpts.GetDisableGerberMacros() );
367
368 // Option for using proper Gerber extensions. Note also Protel extensions are
369 // a broken feature. However, for now, we need to handle it.
370 m_useGerberExtensions->SetValue( m_plotOpts.GetUseGerberProtelExtensions() );
371
372 // Option for including Gerber attributes, from Gerber X2 format, in the output
373 // In X1 format, they will be added as comments
374 m_useGerberX2Format->SetValue( m_plotOpts.GetUseGerberX2format() );
375
376 // Option for including Gerber netlist info (from Gerber X2 format) in the output
377 m_useGerberNetAttributes->SetValue( m_plotOpts.GetIncludeGerberNetlistInfo() );
378
379 // Option to generate a Gerber job file
380 m_generateGerberJobFile->SetValue( m_plotOpts.GetCreateGerberJobFile() );
381
382 // Gerber precision for coordinates
383 m_coordFormatCtrl->SetSelection( m_plotOpts.GetGerberPrecision() == 5 ? 0 : 1 );
384
385 // SVG precision and units for coordinates
386 m_svgPrecsision->SetValue( m_plotOpts.GetSvgPrecision() );
387 m_SVG_fitPageToBoard->SetValue( m_plotOpts.GetSvgFitPagetoBoard() );
388
389 // PNG options
390 m_pngDPI->SetValue( m_plotOpts.GetPngDPI() );
391 m_pngAntialias->SetValue( m_plotOpts.GetPngAntialias() );
392
393 m_sketchPadsOnFabLayers->SetValue( m_plotOpts.GetSketchPadsOnFabLayers() );
394 m_plotPadNumbers->SetValue( m_plotOpts.GetPlotPadNumbers() );
395 m_plotPadNumbers->Enable( m_plotOpts.GetSketchPadsOnFabLayers() );
396
397 m_plotDNP->SetValue( m_plotOpts.GetHideDNPFPsOnFabLayers()
398 || m_plotOpts.GetSketchDNPFPsOnFabLayers()
399 || m_plotOpts.GetCrossoutDNPFPsOnFabLayers() );
400
401 if( m_plotDNP->GetValue() )
402 {
403 if( m_plotOpts.GetHideDNPFPsOnFabLayers() )
404 m_hideDNP->SetValue( true );
405 else
406 m_crossoutDNP->SetValue( true );
407 }
408
409 m_hideDNP->Enable( m_plotDNP->GetValue() );
410 m_crossoutDNP->Enable( m_plotDNP->GetValue() );
411
412 m_subtractMaskFromSilk->SetValue( m_plotOpts.GetSubtractMaskFromSilk() );
413
414 m_useAuxOriginCheckBox->SetValue( m_plotOpts.GetUseAuxOrigin() );
415
416 m_plotSheetRef->SetValue( m_plotOpts.GetPlotFrameRef() );
417
418 // Options to plot pads and vias holes
419 m_drillShapeOpt->SetSelection( (int) m_plotOpts.GetDrillMarksType() );
420
421 // Scale option
422 m_scaleOpt->SetSelection( m_plotOpts.GetScaleSelection() );
423
424 // DXF outline mode
425 m_DXF_plotModeOpt->SetValue( m_plotOpts.GetDXFPlotPolygonMode() );
426
427 // DXF text mode
429
430 // DXF units selection
431 m_DXF_plotUnits->SetSelection( m_plotOpts.GetDXFPlotUnits() == DXF_UNITS::INCH ? 0 : 1 );
432
433 // Job only, PCB_PLOTTER honours this flag for non-DXF formats too
434 if( m_job )
435 m_DXF_exportAsMultiLayeredFile->SetValue( m_plotOpts.GetDXFMultiLayeredExportOption() );
436
437 // Plot mirror option
438 m_plotMirrorOpt->SetValue( m_plotOpts.GetMirror() );
439
440 // Black and white plotting
441 m_SVGColorChoice->SetSelection( m_plotOpts.GetBlackAndWhite() ? 1 : 0 );
442 m_PDFColorChoice->SetSelection( m_plotOpts.GetBlackAndWhite() ? 1 : 0 );
443 m_frontFPPropertyPopups->SetValue( m_plotOpts.m_PDFFrontFPPropertyPopups );
444 m_backFPPropertyPopups->SetValue( m_plotOpts.m_PDFBackFPPropertyPopups );
445 m_pdfMetadata->SetValue( m_plotOpts.m_PDFMetadata );
446 m_pdfSingle->SetValue( m_plotOpts.m_PDFSingle );
447 m_pdfBackgroundColorSwatch->SetSwatchColor( m_plotOpts.m_backgroundColor, false );
449
450 // Initialize a few other parameters, which can also be modified
451 // from the drill dialog
452 reInitDialog();
453
454 // Update options values:
455 wxCommandEvent cmd_event;
456 SetPlotFormat( cmd_event );
457
458 if( m_job )
460
461 return true;
462}
463
464
466{
468 bool singleFile = ( fmt == PLOT_FORMAT::PDF && m_pdfSingle->GetValue() )
469 || ( fmt == PLOT_FORMAT::DXF && m_DXF_exportAsMultiLayeredFile->GetValue() );
470
471 wxString label = singleFile ? _( "Output file:" ) : _( "Output directory:" );
472
473 if( m_staticTextDir->GetLabel() == label )
474 return;
475
476 m_staticTextDir->SetLabel( label );
477
478 if( singleFile )
479 {
480 m_outputDirectoryName->SetToolTip( _( "Target file for the plot. Can be absolute or relative to the board "
481 "file location." ) );
482 }
483 else
484 {
485 m_outputDirectoryName->SetToolTip( _( "Target directory for plot files. Can be absolute or relative to "
486 "the board file location." ) );
487 }
488
489 Layout();
490}
491
492
494{
496 {
497 JOB_EXPORT_PCB_GERBERS* gJob = static_cast<JOB_EXPORT_PCB_GERBERS*>( m_job );
498 gJob->m_disableApertureMacros = m_plotOpts.GetDisableGerberMacros();
499 gJob->m_useProtelFileExtension = m_plotOpts.GetUseGerberProtelExtensions();
500 gJob->m_useX2Format = m_plotOpts.GetUseGerberX2format();
501 gJob->m_includeNetlistAttributes = m_plotOpts.GetIncludeGerberNetlistInfo();
502 gJob->m_createJobsFile = m_plotOpts.GetCreateGerberJobFile();
503 gJob->m_precision = m_plotOpts.GetGerberPrecision();
504 gJob->m_useBoardPlotParams = false;
505 }
506 else
507 {
508 m_job->m_scale = selectionToScale( m_plotOpts.GetScaleSelection() );
509 }
510
511 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::SVG )
512 {
513 JOB_EXPORT_PCB_SVG* svgJob = static_cast<JOB_EXPORT_PCB_SVG*>( m_job );
514 svgJob->m_precision = m_plotOpts.GetSvgPrecision();
516 svgJob->m_fitPageToBoard = m_plotOpts.GetSvgFitPagetoBoard();
517 }
518
519 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::DXF )
520 {
521 JOB_EXPORT_PCB_DXF* dxfJob = static_cast<JOB_EXPORT_PCB_DXF*>( m_job );
525 dxfJob->m_polygonMode = m_plotOpts.GetDXFPlotPolygonMode();
526 dxfJob->m_useKiCadFont = m_plotOpts.GetTextMode() != PLOT_TEXT_MODE::NATIVE;
527 dxfJob->m_genMode = m_plotOpts.GetDXFMultiLayeredExportOption() ? JOB_EXPORT_PCB_DXF::GEN_MODE::SINGLE
529 }
530
531 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::POST )
532 {
533 JOB_EXPORT_PCB_PS* psJob = static_cast<JOB_EXPORT_PCB_PS*>( m_job );
535 psJob->m_XScaleAdjust = m_plotOpts.GetFineScaleAdjustX();
536 psJob->m_YScaleAdjust = m_plotOpts.GetFineScaleAdjustY();
537 psJob->m_trackWidthCorrection = pcbIUScale.IUTomm( m_plotOpts.GetWidthAdjust() );
538 psJob->m_forceA4 = m_plotOpts.GetA4Output();
539 // For a fresh job we got the adjusts from the global pcbnew settings
540 // After the user confirmed and/or changed them we stop using the global adjusts
541 psJob->m_useGlobalSettings = false;
542 }
543
544 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::PDF )
545 {
546 JOB_EXPORT_PCB_PDF* pdfJob = static_cast<JOB_EXPORT_PCB_PDF*>( m_job );
547 pdfJob->m_pdfFrontFPPropertyPopups = m_plotOpts.m_PDFFrontFPPropertyPopups;
548 pdfJob->m_pdfBackFPPropertyPopups = m_plotOpts.m_PDFBackFPPropertyPopups;
549 pdfJob->m_pdfMetadata = m_plotOpts.m_PDFMetadata;
550 pdfJob->m_pdfSingle = m_plotOpts.m_PDFSingle;
551 pdfJob->m_pdfBackgroundColor = m_plotOpts.m_backgroundColor.ToCSSString();
552
553 // we need to embed this for the cli deprecation fix
554 if( pdfJob->m_pdfSingle )
555 {
557 }
558 else
559 {
561 }
562 }
563
564 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::PNG )
565 {
566 JOB_EXPORT_PCB_PNG* pngJob = static_cast<JOB_EXPORT_PCB_PNG*>( m_job );
567 pngJob->m_dpi = m_plotOpts.GetPngDPI();
568 pngJob->m_antialias = m_plotOpts.GetPngAntialias();
569 }
570
571 m_job->m_subtractSolderMaskFromSilk = m_plotOpts.GetSubtractMaskFromSilk();
572 m_job->m_useDrillOrigin = m_plotOpts.GetUseAuxOrigin();
573 m_job->m_crossoutDNPFPsOnFabLayers = m_plotOpts.GetCrossoutDNPFPsOnFabLayers();
574 m_job->m_hideDNPFPsOnFabLayers = m_plotOpts.GetHideDNPFPsOnFabLayers();
575 m_job->m_sketchDNPFPsOnFabLayers = m_plotOpts.GetSketchDNPFPsOnFabLayers();
576 m_job->m_sketchPadsOnFabLayers = m_plotOpts.GetSketchPadsOnFabLayers();
577
578 m_job->m_plotDrawingSheet = m_plotOpts.GetPlotFrameRef();
579 m_job->m_plotPadNumbers = m_plotOpts.GetPlotPadNumbers();
580
581 m_job->m_blackAndWhite = m_plotOpts.GetBlackAndWhite();
582 m_job->m_mirror = m_plotOpts.GetMirror();
583 m_job->m_negative = m_plotOpts.GetNegative();
584 m_job->m_plotLayerSequence = m_plotOpts.GetLayerSelection().SeqStackupForPlotting();
585 m_job->m_plotOnAllLayersSequence = m_plotOpts.GetPlotOnAllLayersSequence();
586
587 if( m_job->m_plotFormat == JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::SVG ||
589 {
590 switch( m_plotOpts.GetDrillMarksType() )
591 {
592 case DRILL_MARKS::NO_DRILL_SHAPE: m_job->m_drillShapeOption = DRILL_MARKS::NO_DRILL_SHAPE; break;
594 default:
595 case DRILL_MARKS::FULL_DRILL_SHAPE: m_job->m_drillShapeOption = DRILL_MARKS::FULL_DRILL_SHAPE; break;
596 }
597 }
598
599 m_job->SetConfiguredOutputPath( m_plotOpts.GetOutputDirectory() );
600
601 // this exists outside plot opts because its usually globally saved
602 m_job->m_checkZonesBeforePlot = m_zoneFillCheck->GetValue();
603
604 m_job->m_variant = getSelectedVariant();
605}
606
607
609{
610 // after calling the Drill or DRC dialogs some parameters can be modified....
611
612 // Output directory
613 m_outputDirectoryName->SetValue( m_plotOpts.GetOutputDirectory() );
614
615 // Origin of coordinates:
616 m_useAuxOriginCheckBox->SetValue( m_plotOpts.GetUseAuxOrigin() );
617
618 int knownViolations = 0;
619 int exclusions = 0;
620
621 for( PCB_MARKER* marker : m_editFrame->GetBoard()->Markers() )
622 {
623 if( marker->GetSeverity() == RPT_SEVERITY_EXCLUSION )
624 exclusions++;
625 else
626 knownViolations++;
627 }
628
629 if( !m_job && ( knownViolations || exclusions ) )
630 {
631 m_DRCExclusionsWarning->SetLabel( wxString::Format( m_DRCWarningTemplate, knownViolations,
632 exclusions ) );
634 }
635 else
636 {
638 }
639
640 BOARD* board = m_editFrame->GetBoard();
641 const BOARD_DESIGN_SETTINGS& brd_settings = board->GetDesignSettings();
642
644 ( brd_settings.m_SolderMaskExpansion || brd_settings.m_SolderMaskMinWidth ) )
645 {
647 }
648 else
649 {
651 }
652}
653
654
656{
657 wxString variant;
658 int selection = m_variantChoiceCtrl->GetSelection();
659
660 if( ( selection != 0 ) && ( selection != wxNOT_FOUND ) )
661 variant = m_variantChoiceCtrl->GetString( selection );
662
663 return variant;
664}
665
666
668{
669 auto findLayer =
670 [&]( wxRearrangeList* aList, PCB_LAYER_ID aLayer ) -> int
671 {
672 for( int ii = 0; ii < (int) aList->GetCount(); ++ii )
673 {
674 if( getLayerClientData( aList, ii )->Layer() == aLayer )
675 return ii;
676 }
677
678 return -1;
679 };
680
681 int idx = 0;
682
683 for( PCB_LAYER_ID layer : aSeq )
684 {
685 int currentPos = findLayer( m_plotAllLayersList, layer );
686
687 while( currentPos > idx )
688 {
689 m_plotAllLayersList->Select( currentPos );
690 m_plotAllLayersList->MoveCurrentUp();
691 currentPos--;
692 }
693
694 idx++;
695 }
696}
697
698
699#define ID_LAYER_FAB 13001
700#define ID_SELECT_COPPER_LAYERS 13002
701#define ID_DESELECT_COPPER_LAYERS 13003
702#define ID_SELECT_ALL_LAYERS 13004
703#define ID_DESELECT_ALL_LAYERS 13005
704#define ID_STACKUP_ORDER 13006
705
706
707// A helper function to show a popup menu, when the dialog is right clicked.
708void DIALOG_PLOT::OnRightClickLayers( wxMouseEvent& event )
709{
710 // Build a list of layers for usual fabrication: copper layers + tech layers without courtyard
711 LSET fab_layer_set = ( LSET::AllCuMask() | LSET::AllTechMask() ) & ~LSET( { B_CrtYd, F_CrtYd } );
712
713 wxMenu menu;
714 menu.Append( new wxMenuItem( &menu, ID_LAYER_FAB, _( "Select Fab Layers" ) ) );
715
716 menu.AppendSeparator();
717 menu.Append( new wxMenuItem( &menu, ID_SELECT_COPPER_LAYERS, _( "Select All Copper Layers" ) ) );
718 menu.Append( new wxMenuItem( &menu, ID_DESELECT_COPPER_LAYERS, _( "Deselect All Copper Layers" ) ) );
719
720 menu.AppendSeparator();
721 menu.Append( new wxMenuItem( &menu, ID_SELECT_ALL_LAYERS, _( "Select All Layers" ) ) );
722 menu.Append( new wxMenuItem( &menu, ID_DESELECT_ALL_LAYERS, _( "Deselect All Layers" ) ) );
723
724 menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
725 [&]( wxCommandEvent& aCmd )
726 {
727 switch( aCmd.GetId() )
728 {
729 case ID_LAYER_FAB: // Select layers usually needed to build a board
730 {
731 for( unsigned i = 0; i < m_layerList.size(); i++ )
732 {
733 LSET layermask( { m_layerList[ i ] } );
734
735 if( ( layermask & fab_layer_set ).any() )
736 m_layerCheckListBox->Check( i, true );
737 else
738 m_layerCheckListBox->Check( i, false );
739 }
740
741 break;
742 }
743
745 for( unsigned i = 0; i < m_layerList.size(); i++ )
746 {
747 if( IsCopperLayer( m_layerList[i] ) )
748 m_layerCheckListBox->Check( i, true );
749 }
750
751 break;
752
754 for( unsigned i = 0; i < m_layerList.size(); i++ )
755 {
756 if( IsCopperLayer( m_layerList[i] ) )
757 m_layerCheckListBox->Check( i, false );
758 }
759
760 break;
761
763 for( unsigned i = 0; i < m_layerList.size(); i++ )
764 m_layerCheckListBox->Check( i, true );
765
766 break;
767
769 for( unsigned i = 0; i < m_layerList.size(); i++ )
770 m_layerCheckListBox->Check( i, false );
771
772 break;
773
774 default:
775 aCmd.Skip();
776 }
777 } );
778
779 PopupMenu( &menu );
780}
781
782
783void DIALOG_PLOT::OnRightClickAllLayers( wxMouseEvent& event )
784{
785 wxMenu menu;
786 menu.Append( new wxMenuItem( &menu, ID_SELECT_ALL_LAYERS, _( "Select All Layers" ) ) );
787 menu.Append( new wxMenuItem( &menu, ID_DESELECT_ALL_LAYERS, _( "Deselect All Layers" ) ) );
788
789 menu.AppendSeparator();
790 menu.Append( new wxMenuItem( &menu, ID_STACKUP_ORDER, _( "Order as Board Stackup" ) ) );
791
792 menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
793 [&]( wxCommandEvent& aCmd )
794 {
795 switch( aCmd.GetId() )
796 {
798 for( unsigned i = 0; i < m_plotAllLayersList->GetCount(); i++ )
799 m_plotAllLayersList->Check( i, true );
800
801 break;
802
804 for( unsigned i = 0; i < m_plotAllLayersList->GetCount(); i++ )
805 m_plotAllLayersList->Check( i, false );
806
807 break;
808
809 case ID_STACKUP_ORDER:
810 {
811 LSEQ stackup = m_editFrame->GetBoard()->GetEnabledLayers().SeqStackupForPlotting();
812 arrangeAllLayersList( stackup );
813 m_plotAllLayersList->Select( -1 );
814 break;
815 }
816
817 default:
818 aCmd.Skip();
819 }
820 } );
821
822 PopupMenu( &menu );
823}
824
825
826void DIALOG_PLOT::CreateDrillFile( wxCommandEvent& event )
827{
828 // Be sure drill file use the same settings (axis option, plot directory) as plot files:
830
831 DIALOG_GENDRILL dlg( m_editFrame, this );
832 dlg.ShowModal();
833
834 // a few plot settings can be modified: take them in account
835 m_plotOpts = m_editFrame->GetPlotSettings();
836 reInitDialog();
837}
838
839
840void DIALOG_PLOT::OnChangeDXFPlotMode( wxCommandEvent& event )
841{
842 // m_DXF_plotTextStrokeFontOpt is disabled if m_DXF_plotModeOpt is checked (plot in DXF
843 // polygon mode)
844 m_DXF_plotTextStrokeFontOpt->Enable( !m_DXF_plotModeOpt->GetValue() );
845
846 // if m_DXF_plotTextStrokeFontOpt option is disabled (plot DXF in polygon mode), force
847 // m_DXF_plotTextStrokeFontOpt to true to use Pcbnew stroke font
848 if( !m_DXF_plotTextStrokeFontOpt->IsEnabled() )
849 m_DXF_plotTextStrokeFontOpt->SetValue( true );
850}
851
852
854{
855 // Build the absolute path of current output directory to preselect it in the file browser.
856 std::function<bool( wxString* )> textResolver =
857 [&]( wxString* token ) -> bool
858 {
859 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
860 };
861
862 wxString path = ResolveProjectPath( m_outputDirectoryName->GetValue(), &Prj(), &textResolver );
863
864 wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
865
866 if( dirDialog.ShowModal() == wxID_CANCEL )
867 return;
868
869 wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
870
871 wxFileName fn( Prj().AbsolutePath( m_editFrame->GetBoard()->GetFileName() ) );
872 wxString defaultPath = fn.GetPathWithSep();
873 wxFileName relPathTest; // Used to test if we can make the path relative
874
875 relPathTest.Assign( dirDialog.GetPath() );
876
877 // Test if making the path relative is possible before asking the user if they want to do it
878 if( relPathTest.MakeRelativeTo( defaultPath ) )
879 {
880 if( IsOK( this, wxString::Format( _( "Do you want to use a path relative to\n'%s'?" ), defaultPath ) ) )
881 dirName.MakeRelativeTo( defaultPath );
882 }
883
884 m_outputDirectoryName->SetValue( dirName.GetFullPath() );
885}
886
887
889{
890 // plot format id's are ordered like displayed in m_plotFormatOpt
891 static const PLOT_FORMAT plotFmt[] = {
898
899 return plotFmt[m_plotFormatOpt->GetSelection()];
900}
901
902
903void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
904{
905 // this option exist only in DXF format:
907
908 // The alert message about non 0 solder mask min width and margin is shown
909 // only in gerber format and if min mask width or mask margin is not 0
910 BOARD* board = m_editFrame->GetBoard();
911 const BOARD_DESIGN_SETTINGS& brd_settings = board->GetDesignSettings();
912
914 && ( brd_settings.m_SolderMaskExpansion || brd_settings.m_SolderMaskMinWidth ) )
915 {
917 }
918 else
919 {
921 }
922
923 wxSizer* shownFormatSizer = nullptr;
924
925 switch( getPlotFormat() )
926 {
927 case PLOT_FORMAT::SVG:
928 case PLOT_FORMAT::PDF:
929 m_drillShapeOpt->Enable( true );
930 m_plotMirrorOpt->Enable( true );
931 m_useAuxOriginCheckBox->Enable( true );
932 m_scaleOpt->Enable( true );
933 m_fineAdjustXCtrl->Enable( false );
934 m_fineAdjustYCtrl->Enable( false );
935 m_trackWidthCorrection.Enable( false );
936 m_plotPSNegativeOpt->Enable( true );
937 m_forcePSA4OutputOpt->Enable( false );
938 m_forcePSA4OutputOpt->SetValue( false );
939
941 break;
942
944 m_drillShapeOpt->Enable( true );
945 m_plotMirrorOpt->Enable( true );
946 m_useAuxOriginCheckBox->Enable( false );
947 m_useAuxOriginCheckBox->SetValue( false );
948 m_scaleOpt->Enable( true );
949 m_fineAdjustXCtrl->Enable( true );
950 m_fineAdjustYCtrl->Enable( true );
951 m_trackWidthCorrection.Enable( true );
952 m_plotPSNegativeOpt->Enable( true );
953 m_forcePSA4OutputOpt->Enable( true );
954
955 shownFormatSizer = m_PSOptionsSizer;
956 break;
957
959 m_drillShapeOpt->Enable( false );
960 m_drillShapeOpt->SetSelection( 0 );
961 m_plotMirrorOpt->Enable( false );
962 m_plotMirrorOpt->SetValue( false );
963 m_useAuxOriginCheckBox->Enable( true );
964 m_scaleOpt->Enable( false );
965 m_scaleOpt->SetSelection( 1 );
966 m_fineAdjustXCtrl->Enable( false );
967 m_fineAdjustYCtrl->Enable( false );
968 m_trackWidthCorrection.Enable( false );
969 m_plotPSNegativeOpt->Enable( false );
970 m_plotPSNegativeOpt->SetValue( false );
971 m_forcePSA4OutputOpt->Enable( false );
972 m_forcePSA4OutputOpt->SetValue( false );
973
974 shownFormatSizer = m_GerberOptionsSizer;
975 break;
976
977 case PLOT_FORMAT::DXF:
978 m_drillShapeOpt->Enable( true );
979 m_plotMirrorOpt->Enable( false );
980 m_plotMirrorOpt->SetValue( false );
981 m_useAuxOriginCheckBox->Enable( true );
982 m_scaleOpt->Enable( true );
983 m_fineAdjustXCtrl->Enable( false );
984 m_fineAdjustYCtrl->Enable( false );
985 m_trackWidthCorrection.Enable( false );
986 m_plotPSNegativeOpt->Enable( false );
987 m_plotPSNegativeOpt->SetValue( false );
988 m_forcePSA4OutputOpt->Enable( false );
989 m_forcePSA4OutputOpt->SetValue( false );
990
991 shownFormatSizer = m_SizerDXF_options;
992 OnChangeDXFPlotMode( event );
993 break;
994
995 case PLOT_FORMAT::PNG:
996 m_drillShapeOpt->Enable( true );
997 m_plotMirrorOpt->Enable( true );
998 m_useAuxOriginCheckBox->Enable( true );
999 m_scaleOpt->Enable( true );
1000 m_fineAdjustXCtrl->Enable( false );
1001 m_fineAdjustYCtrl->Enable( false );
1002 m_trackWidthCorrection.Enable( false );
1003 m_plotPSNegativeOpt->Enable( true );
1004 m_forcePSA4OutputOpt->Enable( false );
1005 m_forcePSA4OutputOpt->SetValue( false );
1006
1007 shownFormatSizer = m_pngOptionsSizer;
1008 break;
1009
1010 default:
1011 case PLOT_FORMAT::HPGL:
1013 break;
1014 }
1015
1016 for( wxSizer* formatSizer : { m_GerberOptionsSizer, m_PSOptionsSizer, m_SizerDXF_options,
1018 {
1019 m_PlotOptionsSizer->Show( formatSizer, formatSizer == shownFormatSizer );
1020 }
1021
1022 Layout();
1023 m_MainSizer->SetSizeHints( this );
1024}
1025
1026
1027// A helper function to "clip" aValue between aMin and aMax and write result in * aResult
1028// return false if clipped, true if aValue is just copied into * aResult
1029static bool setDouble( double* aResult, double aValue, double aMin, double aMax )
1030{
1031 if( aValue < aMin )
1032 {
1033 *aResult = aMin;
1034 return false;
1035 }
1036 else if( aValue > aMax )
1037 {
1038 *aResult = aMax;
1039 return false;
1040 }
1041
1042 *aResult = aValue;
1043 return true;
1044}
1045
1046
1047static bool setInt( int* aResult, int aValue, int aMin, int aMax )
1048{
1049 if( aValue < aMin )
1050 {
1051 *aResult = aMin;
1052 return false;
1053 }
1054 else if( aValue > aMax )
1055 {
1056 *aResult = aMax;
1057 return false;
1058 }
1059
1060 *aResult = aValue;
1061 return true;
1062}
1063
1064
1066{
1067 REPORTER& reporter = m_messagesPanel->Reporter();
1068 PCB_PLOT_PARAMS tempOptions;
1069
1070 tempOptions.SetDashedLineDashRatio( m_plotOpts.GetDashedLineDashRatio() );
1071 tempOptions.SetDashedLineGapRatio( m_plotOpts.GetDashedLineGapRatio() );
1072
1073 tempOptions.SetSubtractMaskFromSilk( m_subtractMaskFromSilk->GetValue() );
1074 tempOptions.SetPlotFrameRef( m_plotSheetRef->GetValue() );
1075 tempOptions.SetSketchPadsOnFabLayers( m_sketchPadsOnFabLayers->GetValue() );
1076 tempOptions.SetPlotPadNumbers( m_plotPadNumbers->GetValue() );
1077 tempOptions.SetHideDNPFPsOnFabLayers( m_plotDNP->GetValue()
1078 && m_hideDNP->GetValue() );
1079 tempOptions.SetSketchDNPFPsOnFabLayers( m_plotDNP->GetValue()
1080 && m_crossoutDNP->GetValue() );
1081 tempOptions.SetCrossoutDNPFPsOnFabLayers( m_plotDNP->GetValue()
1082 && m_crossoutDNP->GetValue() );
1083 tempOptions.SetUseAuxOrigin( m_useAuxOriginCheckBox->GetValue() );
1084 tempOptions.SetScaleSelection( m_scaleOpt->GetSelection() );
1085
1086 int sel = m_drillShapeOpt->GetSelection();
1087 tempOptions.SetDrillMarksType( static_cast<DRILL_MARKS>( sel ) );
1088
1089 tempOptions.SetMirror( m_plotMirrorOpt->GetValue() );
1090 tempOptions.SetDXFPlotPolygonMode( m_DXF_plotModeOpt->GetValue() );
1091
1092 sel = m_DXF_plotUnits->GetSelection();
1093 tempOptions.SetDXFPlotUnits( sel == 0 ? DXF_UNITS::INCH : DXF_UNITS::MM );
1094
1095 if( !m_DXF_plotTextStrokeFontOpt->IsEnabled() ) // Currently, only DXF supports this option
1096 tempOptions.SetTextMode( PLOT_TEXT_MODE::DEFAULT );
1097 else
1100
1102
1104 {
1105 tempOptions.SetBlackAndWhite( m_SVGColorChoice->GetSelection() == 1 );
1106 }
1107 else if( getPlotFormat() == PLOT_FORMAT::PDF )
1108 {
1109 tempOptions.SetBlackAndWhite( m_PDFColorChoice->GetSelection() == 1 );
1110 tempOptions.m_PDFFrontFPPropertyPopups = m_frontFPPropertyPopups->GetValue();
1111 tempOptions.m_PDFBackFPPropertyPopups = m_backFPPropertyPopups->GetValue();
1112 tempOptions.m_PDFMetadata = m_pdfMetadata->GetValue();
1113 tempOptions.m_PDFSingle = m_pdfSingle->GetValue();
1114 tempOptions.m_backgroundColor = m_pdfBackgroundColorSwatch->GetSwatchColor();
1115 }
1116 else if( getPlotFormat() == PLOT_FORMAT::PNG )
1117 {
1118 // Match the CLI default; a dedicated UI control will be added with the next .fbp regen.
1119 tempOptions.SetBlackAndWhite( false );
1120 }
1121 else
1122 {
1123 tempOptions.SetBlackAndWhite( true );
1124 }
1125
1126 // Update settings from text fields. Rewrite values back to the fields,
1127 // since the values may have been constrained by the setters.
1128
1129 // X scale
1130 double tmpDouble;
1131 wxString msg = m_fineAdjustXCtrl->GetValue();
1132 msg.ToDouble( &tmpDouble );
1133
1135 {
1136 msg.Printf( wxT( "%f" ), m_XScaleAdjust );
1137 m_fineAdjustXCtrl->SetValue( msg );
1138 msg.Printf( _( "X scale constrained." ) );
1139 reporter.Report( msg, RPT_SEVERITY_INFO );
1140 }
1141
1142 // Y scale
1143 msg = m_fineAdjustYCtrl->GetValue();
1144 msg.ToDouble( &tmpDouble );
1145
1147 {
1148 msg.Printf( wxT( "%f" ), m_YScaleAdjust );
1149 m_fineAdjustYCtrl->SetValue( msg );
1150 msg.Printf( _( "Y scale constrained." ) );
1151 reporter.Report( msg, RPT_SEVERITY_INFO );
1152 }
1153
1154 // PS Width correction
1157 {
1159 msg.Printf( _( "Width correction constrained. The width correction value must be in the"
1160 " range of [%s; %s] for the current design rules." ),
1161 m_editFrame->StringFromValue( m_widthAdjustMinValue, true ),
1162 m_editFrame->StringFromValue( m_widthAdjustMaxValue, true ) );
1163 reporter.Report( msg, RPT_SEVERITY_WARNING );
1164 }
1165
1166 if( m_job )
1167 {
1168 // When using a job we store the adjusts in the plot options
1169 tempOptions.SetFineScaleAdjustX( m_XScaleAdjust );
1170 tempOptions.SetFineScaleAdjustY( m_YScaleAdjust );
1171 tempOptions.SetWidthAdjust( m_PSWidthAdjust );
1172 }
1173
1174 tempOptions.SetFormat( getPlotFormat() );
1175
1176 tempOptions.SetDisableGerberMacros( m_disableApertMacros->GetValue() );
1177 tempOptions.SetUseGerberProtelExtensions( m_useGerberExtensions->GetValue() );
1178 tempOptions.SetUseGerberX2format( m_useGerberX2Format->GetValue() );
1179 tempOptions.SetIncludeGerberNetlistInfo( m_useGerberNetAttributes->GetValue() );
1180 tempOptions.SetCreateGerberJobFile( m_generateGerberJobFile->GetValue() );
1181
1182 tempOptions.SetGerberPrecision( m_coordFormatCtrl->GetSelection() == 0 ? 5 : 6 );
1183 tempOptions.SetSvgPrecision( m_svgPrecsision->GetValue() );
1184 tempOptions.SetSvgFitPageToBoard( m_SVG_fitPageToBoard->GetValue() );
1185 tempOptions.SetPngDPI( m_pngDPI->GetValue() );
1186 tempOptions.SetPngAntialias( m_pngAntialias->GetValue() );
1187
1188 LSET selectedLayers;
1189
1190 for( unsigned i = 0; i < m_layerList.size(); i++ )
1191 {
1192 if( m_layerCheckListBox->IsChecked( i ) )
1193 selectedLayers.set( m_layerList[i] );
1194 }
1195
1196 // Get a list of copper layers that aren't being used by inverting enabled layers.
1197 LSET disabledCopperLayers = LSET::AllCuMask() & ~m_editFrame->GetBoard()->GetEnabledLayers();
1198
1199 // Add selected layers from plot on all layers list in order set by user.
1200 wxArrayInt plotOnAllLayers;
1201 LSEQ commonLayers;
1202
1203 if( m_plotAllLayersList->GetCheckedItems( plotOnAllLayers ) )
1204 {
1205 size_t count = plotOnAllLayers.GetCount();
1206
1207 for( size_t i = 0; i < count; i++ )
1208 {
1209 int index = plotOnAllLayers.Item( i );
1211
1212 commonLayers.push_back( client_layer );
1213 }
1214 }
1215
1216 tempOptions.SetPlotOnAllLayersSequence( commonLayers );
1217
1218 // Enable all of the disabled copper layers.
1219 // If someone enables more copper layers they will be selected by default.
1220 selectedLayers = selectedLayers | disabledCopperLayers;
1221 tempOptions.SetLayerSelection( selectedLayers );
1222
1223 tempOptions.SetNegative( m_plotPSNegativeOpt->GetValue() );
1224 tempOptions.SetA4Output( m_forcePSA4OutputOpt->GetValue() );
1225
1226 // Set output directory and replace backslashes with forward ones
1227 wxString dirStr;
1228 dirStr = m_outputDirectoryName->GetValue();
1229 dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
1230 tempOptions.SetOutputDirectory( dirStr );
1231 m_editFrame->Prj().GetProjectFile().m_PcbLastPath[ LAST_PATH_PLOT ] = dirStr;
1232
1233 if( !m_job && !m_plotOpts.IsSameAs( tempOptions ) )
1234 {
1235 m_editFrame->SetPlotSettings( tempOptions );
1236 m_editFrame->OnModify();
1237 m_plotOpts = tempOptions;
1238 }
1239 else
1240 {
1241 m_plotOpts = tempOptions;
1242 }
1243}
1244
1245
1246void DIALOG_PLOT::OnGerberX2Checked( wxCommandEvent& event )
1247{
1248 // Currently: do nothing
1249}
1250
1251
1252void DIALOG_PLOT::Plot( wxCommandEvent& event )
1253{
1254 if( m_job )
1255 {
1258 EndModal( wxID_OK );
1259 }
1260 else
1261 {
1262 BOARD* board = m_editFrame->GetBoard();
1263
1265
1267
1268 m_plotOpts.SetColorSettings( ::GetColorSettings( cfg ? cfg->m_ColorTheme : DEFAULT_THEME ) );
1269
1270 m_plotOpts.SetSketchPadLineWidth( board->GetDesignSettings().GetLineThickness( F_Fab ) );
1271
1272 // If no layer selected, we have nothing plotted.
1273 // Prompt user if it happens because he could think there is a bug in Pcbnew.
1274 if( !m_plotOpts.GetLayerSelection().any() )
1275 {
1276 DisplayError( this, _( "No layer selected, Nothing to plot" ) );
1277 return;
1278 }
1279
1280 // Create output directory if it does not exist (also transform it in absolute form).
1281 // Bail if it fails.
1282
1283 std::function<bool( wxString* )> textResolver =
1284 [&]( wxString* token ) -> bool
1285 {
1286 // Handles board->GetTitleBlock() *and* board->GetProject()
1287 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
1288 };
1289
1290 wxString path = ExpandPathVariables( m_plotOpts.GetOutputDirectory(), board->GetProject(), &textResolver );
1291
1292 wxFileName outputDir = wxFileName::DirName( path );
1293 wxString boardFilename = m_editFrame->GetBoard()->GetFileName();
1294 REPORTER& reporter = m_messagesPanel->Reporter();
1295
1296 if( !EnsureFileDirectoryExists( &outputDir, boardFilename, &reporter ) )
1297 {
1298 wxString msg;
1299 msg.Printf( _( "Could not write plot files to folder '%s'." ), outputDir.GetPath() );
1300 DisplayError( this, msg );
1301 return;
1302 }
1303
1304 if( m_zoneFillCheck->GetValue() )
1305 m_editFrame->GetToolManager()->GetTool<ZONE_FILLER_TOOL>()->CheckAllZones( this );
1306
1307 m_plotOpts.SetAutoScale( false );
1308
1309 switch( m_plotOpts.GetScaleSelection() )
1310 {
1311 default: m_plotOpts.SetScale( 1 ); break;
1312 case 0: m_plotOpts.SetAutoScale( true ); break;
1313 case 2: m_plotOpts.SetScale( 1.5 ); break;
1314 case 3: m_plotOpts.SetScale( 2 ); break;
1315 case 4: m_plotOpts.SetScale( 3 ); break;
1316 }
1317
1318 /* If the scale factor edit controls are disabled or the scale value
1319 * is 0, don't adjust the base scale factor. This fixes a bug when
1320 * the default scale adjust is initialized to 0 and saved in program
1321 * settings resulting in a divide by zero fault.
1322 */
1324 {
1325 if( m_XScaleAdjust != 0.0 )
1326 m_plotOpts.SetFineScaleAdjustX( m_XScaleAdjust );
1327
1328 if( m_YScaleAdjust != 0.0 )
1329 m_plotOpts.SetFineScaleAdjustY( m_YScaleAdjust );
1330
1331 m_plotOpts.SetWidthAdjust( m_PSWidthAdjust );
1332 }
1333
1334 // Test for a reasonable scale value
1335 // XXX could this actually happen? isn't it constrained in the apply function?
1336 if( m_plotOpts.GetScale() < PLOT_MIN_SCALE )
1337 DisplayInfoMessage( this, _( "Warning: Scale option set to a very small value" ) );
1338
1339 if( m_plotOpts.GetScale() > PLOT_MAX_SCALE )
1340 DisplayInfoMessage( this, _( "Warning: Scale option set to a very large value" ) );
1341
1342
1343 // Save the current plot options in the board
1344 m_editFrame->SetPlotSettings( m_plotOpts );
1345
1346 wxString oldVariant = board->GetCurrentVariant();
1348
1349 PCB_PLOTTER pcbPlotter( m_editFrame->GetBoard(), &reporter, m_plotOpts );
1350
1351 LSEQ layersToPlot = m_plotOpts.GetLayerSelection().UIOrder();
1352
1353 wxArrayInt plotOnAllLayers;
1354 LSEQ commonLayers;
1355
1356 if( m_plotAllLayersList->GetCheckedItems( plotOnAllLayers ) )
1357 {
1358 size_t count = plotOnAllLayers.GetCount();
1359
1360 for( size_t i = 0; i < count; i++ )
1361 {
1362 int index = plotOnAllLayers.Item( i );
1364
1365 commonLayers.push_back( client_layer );
1366 }
1367 }
1368
1369 pcbPlotter.Plot( outputDir.GetPath(), layersToPlot, commonLayers, m_useGerberExtensions->GetValue() );
1370
1371 board->SetCurrentVariant( oldVariant );
1372 }
1373}
1374
1375
1376
1377void DIALOG_PLOT::onRunDRC( wxCommandEvent& event )
1378{
1379 PCB_EDIT_FRAME* parent = dynamic_cast<PCB_EDIT_FRAME*>( GetParent() );
1380
1381 if( parent )
1382 {
1383 DRC_TOOL* drcTool = parent->GetToolManager()->GetTool<DRC_TOOL>();
1384
1385 // First close an existing dialog if open
1386 // (low probability, but can happen)
1387 drcTool->DestroyDRCDialog();
1388
1389 // Open a new drc dialog, with the right parent frame, and in Modal Mode
1390 drcTool->ShowDRCDialog( this );
1391
1392 // Update DRC warnings on return to this dialog
1393 reInitDialog();
1394 }
1395}
1396
1397
1398void DIALOG_PLOT::onOpenOutputDirectory( wxCommandEvent& event )
1399{
1400 std::function<bool( wxString* )> textResolver =
1401 [&]( wxString* token ) -> bool
1402 {
1403 return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
1404 };
1405
1406 wxString path = ResolveProjectPath( m_outputDirectoryName->GetValue(), &Prj(), &textResolver );
1407
1408 if( !wxDirExists( path ) )
1409 {
1410 DisplayError( this, wxString::Format( _( "Directory '%s' does not exist." ), path ) );
1411 return;
1412 }
1413
1414 wxLaunchDefaultApplication( path );
1415}
1416
1417
1418void DIALOG_PLOT::onBoardSetup( wxHyperlinkEvent& aEvent )
1419{
1420 PCB_EDIT_FRAME* parent = dynamic_cast<PCB_EDIT_FRAME*>( GetParent() );
1421
1422 if( parent )
1423 {
1424 parent->ShowBoardSetupDialog( _( "Solder Mask/Paste" ) );
1425
1426 // Update warnings on return to this dialog
1427 reInitDialog();
1428 }
1429}
1430
1431
1432void DIALOG_PLOT::onPlotAllListMoveUp( wxCommandEvent& aEvent )
1433{
1434 if( m_plotAllLayersList->CanMoveCurrentUp() )
1435 m_plotAllLayersList->MoveCurrentUp();
1436}
1437
1438
1439void DIALOG_PLOT::onPlotAllListMoveDown( wxCommandEvent& aEvent )
1440{
1441 if( m_plotAllLayersList->CanMoveCurrentDown() )
1442 m_plotAllLayersList->MoveCurrentDown();
1443}
1444
1445
1446void DIALOG_PLOT::onDNPCheckbox( wxCommandEvent& aEvent )
1447{
1448 m_hideDNP->Enable( aEvent.IsChecked() );
1449 m_crossoutDNP->Enable( aEvent.IsChecked() );
1450}
1451
1452
1453void DIALOG_PLOT::onSketchPads( wxCommandEvent& aEvent )
1454{
1455 m_plotPadNumbers->Enable( aEvent.IsChecked() );
1456}
1457
1458
1460{
1461 if( m_PDFColorChoice->GetSelection() == 1 )
1462 {
1463 m_pdfBackgroundColorSwatch->Disable();
1464 m_pdfBackgroundColorText->Disable();
1465 }
1466 else
1467 {
1469 m_pdfBackgroundColorText->Enable();
1470 }
1471}
1472
1473
1474void DIALOG_PLOT::onPDFColorChoice( wxCommandEvent& aEvent )
1475{
1477}
int index
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
constexpr EDA_IU_SCALE unityScale
Definition base_units.h:131
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
@ small_new_window
wxString m_ColorTheme
Active color theme name.
BASE_SET & set(size_t pos)
Definition base_set.h:126
Container for design settings for a BOARD object.
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:411
void SetCurrentVariant(const wxString &aVariant)
Definition board.cpp:2969
wxArrayString GetVariantNamesForUI() const
Return the variant names for UI display.
Definition board.cpp:3161
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:932
wxString GetCurrentVariant() const
Definition board.h:530
PROJECT * GetProject() const
Definition board.h:774
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:1174
BOARD_DESIGN_SETTINGS & GetDesignSettings()
Definition board.cpp:1290
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:400
wxCheckBox * m_frontFPPropertyPopups
wxStaticText * m_DRCExclusionsWarning
wxTextCtrl * m_widthAdjustCtrl
wxCheckBox * m_backFPPropertyPopups
wxTextCtrl * m_fineAdjustXCtrl
wxBoxSizer * bmiddleSizer
wxStaticBoxSizer * m_PDFOptionsSizer
wxCheckBox * m_disableApertMacros
wxChoice * m_coordFormatCtrl
wxCheckBox * m_DXF_plotModeOpt
wxCheckBox * m_pdfSingle
wxChoice * m_SVGColorChoice
wxStaticText * m_staticTextPlotFmt
wxStaticBoxSizer * m_pngOptionsSizer
wxCheckBox * m_DXF_exportAsMultiLayeredFile
STD_BITMAP_BUTTON * m_browseButton
wxTextCtrl * m_outputDirectoryName
wxSpinCtrl * m_svgPrecsision
wxTextCtrl * m_fineAdjustYCtrl
wxCheckBox * m_plotPadNumbers
wxCheckBox * m_useAuxOriginCheckBox
wxStaticBoxSizer * m_PSOptionsSizer
STD_BITMAP_BUTTON * m_openDirButton
wxCheckBox * m_plotPSNegativeOpt
wxChoice * m_variantChoiceCtrl
wxStaticText * m_widthAdjustLabel
wxCheckBox * m_SVG_fitPageToBoard
wxStaticText * m_pdfBackgroundColorText
wxCheckBox * m_DXF_plotTextStrokeFontOpt
wxCheckBox * m_useGerberExtensions
wxCheckBox * m_plotSheetRef
wxBoxSizer * m_SizerSolderMaskAlert
wxCheckBox * m_generateGerberJobFile
wxRadioButton * m_crossoutDNP
wxButton * m_sdbSizer1Apply
wxCheckBox * m_useGerberX2Format
wxCheckListBox * m_layerCheckListBox
wxCheckBox * m_plotMirrorOpt
wxStaticText * m_staticTextDir
wxStaticText * m_widthAdjustUnits
wxStaticBoxSizer * m_svgOptionsSizer
COLOR_SWATCH * m_pdfBackgroundColorSwatch
wxCheckBox * m_forcePSA4OutputOpt
wxCheckBox * m_useGerberNetAttributes
wxCheckBox * m_sketchPadsOnFabLayers
wxCheckBox * m_pngAntialias
wxCheckBox * m_subtractMaskFromSilk
wxCheckBox * m_plotDNP
wxBoxSizer * m_PlotOptionsSizer
wxSpinCtrl * m_pngDPI
wxChoice * m_DXF_plotUnits
DIALOG_PLOT_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Plot"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
wxStaticBoxSizer * m_SizerDXF_options
wxCheckBox * m_pdfMetadata
wxChoice * m_drillShapeOpt
wxRadioButton * m_hideDNP
wxCheckBox * m_zoneFillCheck
wxStaticBoxSizer * m_GerberOptionsSizer
WX_HTML_REPORT_PANEL * m_messagesPanel
wxChoice * m_PDFColorChoice
wxChoice * m_plotFormatOpt
wxBoxSizer * m_MainSizer
void onPDFColorChoice(wxCommandEvent &event) override
DIALOG_PLOT(PCB_EDIT_FRAME *aEditFrame)
void reInitDialog()
void OnRightClickLayers(wxMouseEvent &event)
static LSEQ s_lastAllLayersOrder
The plot on all layers ordering the last time the dialog was opened.
JOB_EXPORT_PCB_PLOT * m_job
PCB_PLOT_PARAMS m_plotOpts
Definition dialog_plot.h:96
STD_BITMAP_BUTTON * m_bpMoveUp
void onPlotAllListMoveUp(wxCommandEvent &aEvent)
void OnChangeDXFPlotMode(wxCommandEvent &event) override
int m_widthAdjustMinValue
Definition dialog_plot.h:89
UNIT_BINDER m_trackWidthCorrection
Definition dialog_plot.h:92
void onBoardSetup(wxHyperlinkEvent &aEvent) override
void OnRightClickAllLayers(wxMouseEvent &event)
void onSketchPads(wxCommandEvent &event) override
void Plot(wxCommandEvent &event) override
void applyPlotSettings()
int m_PSWidthAdjust
Definition dialog_plot.h:85
wxString m_DRCWarningTemplate
Definition dialog_plot.h:94
wxRearrangeList * m_plotAllLayersList
Definition dialog_plot.h:98
bool TransferDataToWindow() override
void onPlotAllListMoveDown(wxCommandEvent &aEvent)
void onRunDRC(wxCommandEvent &event) override
void arrangeAllLayersList(const LSEQ &aSeq)
double m_YScaleAdjust
Definition dialog_plot.h:83
void onOpenOutputDirectory(wxCommandEvent &event) override
void updatePdfColorOptions()
PCB_EDIT_FRAME * m_editFrame
Definition dialog_plot.h:79
virtual ~DIALOG_PLOT()
STD_BITMAP_BUTTON * m_bpMoveDown
void updateJobOutputLabel()
wxString getSelectedVariant() const
void CreateDrillFile(wxCommandEvent &event) override
void onDNPCheckbox(wxCommandEvent &event) override
double m_XScaleAdjust
Definition dialog_plot.h:81
PLOT_FORMAT getPlotFormat()
void transferPlotParamsToJob()
int m_widthAdjustMaxValue
Definition dialog_plot.h:90
void onOutputDirectoryBrowseClicked(wxCommandEvent &event) override
void OnGerberX2Checked(wxCommandEvent &event) override
void SetPlotFormat(wxCommandEvent &event) override
LSEQ m_layerList
Definition dialog_plot.h:80
void SetupStandardButtons(std::map< int, wxString > aLabels={})
std::string m_hash_key
int ShowModal() override
void ShowDRCDialog(wxWindow *aParent)
Opens the DRC dialog.
Definition drc_tool.cpp:74
void DestroyDRCDialog()
Close and free the DRC dialog.
Definition drc_tool.cpp:125
@ ALL_LAYERS_SEPARATE_FILE
The most traditional output mode KiCad has had.
@ ONE_PAGE_PER_LAYER_ONE_FILE
"Single Document" mode
wxString m_pdfBackgroundColor
The background color specified in a hex string.
GEN_MODE m_pdfGenMode
uused by the cli, will be removed when the other behavior is deprecated
virtual wxString GetSettingsDialogTitle() const
Definition job.cpp:80
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition lseq.h:47
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:604
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
Definition lset.cpp:739
LSEQ SeqStackupForPlotting() const
Return the sequence that is typical for a bottom-to-top stack-up.
Definition lset.cpp:400
static const LSET & AllTechMask()
Return a mask holding all technical layers (no CU layer) on both side.
Definition lset.cpp:672
The main frame for Pcbnew.
void ShowBoardSetupDialog(const wxString &aInitialPage=wxEmptyString, wxWindow *aParent=nullptr)
A helper wxWidgets control client data object to store layer IDs.
PCB_LAYER_ID Layer() const
void SetData(PCB_LAYER_ID aId)
PCB_LAYER_ID_CLIENT_DATA(PCB_LAYER_ID aId)
static void PlotJobToPlotOpts(PCB_PLOT_PARAMS &aOpts, JOB_EXPORT_PCB_PLOT *aJob, REPORTER &aReporter)
True when the board's out-of-date-chart policy regenerated charts during the last Plot().
bool Plot(const wxString &aOutputPath, const LSEQ &aLayersToPlot, const LSEQ &aCommonLayers, bool aUseGerberFileExtensions, bool aOutputPathIsSingle=false, std::optional< wxString > aLayerName=std::nullopt, std::optional< wxString > aSheetName=std::nullopt, std::optional< wxString > aSheetPath=std::nullopt, std::vector< wxString > *aOutputFiles=nullptr)
Parameters and options when plotting/printing a board.
void SetDrillMarksType(DRILL_MARKS aVal)
void SetLayerSelection(const LSET &aSelection)
void SetOutputDirectory(const wxString &aDir)
void SetSketchPadsOnFabLayers(bool aFlag)
void SetUseGerberX2format(bool aUse)
void SetA4Output(int aForce)
void SetPlotOnAllLayersSequence(LSEQ aSeq)
void SetDXFPlotPolygonMode(bool aFlag)
void SetPlotFrameRef(bool aFlag)
void SetSketchDNPFPsOnFabLayers(bool aFlag)
bool m_PDFMetadata
Generate PDF metadata for SUBJECT and AUTHOR.
void SetDashedLineGapRatio(double aVal)
void SetPlotPadNumbers(bool aFlag)
COLOR4D m_backgroundColor
Background color to use for PNG and PDF plotting.
bool m_PDFFrontFPPropertyPopups
Generate PDF property popup menus for footprints.
void SetDisableGerberMacros(bool aDisable)
void SetDXFMultiLayeredExportOption(bool aFlag)
void SetScaleSelection(int aSelection)
void SetFineScaleAdjustX(double aVal)
void SetMirror(bool aFlag)
void SetBlackAndWhite(bool blackAndWhite)
void SetGerberPrecision(int aPrecision)
void SetSubtractMaskFromSilk(bool aSubtract)
void SetHideDNPFPsOnFabLayers(bool aFlag)
void SetPngDPI(int aDPI)
void SetUseGerberProtelExtensions(bool aUse)
void SetDashedLineDashRatio(double aVal)
void SetDXFPlotUnits(DXF_UNITS aUnit)
void SetPngAntialias(bool aFlag)
void SetIncludeGerberNetlistInfo(bool aUse)
void SetCreateGerberJobFile(bool aCreate)
bool m_PDFSingle
Generate a single PDF file for all layers.
void SetNegative(bool aFlag)
void SetUseAuxOrigin(bool aAux)
bool m_PDFBackFPPropertyPopups
on front and/or back of board
void SetTextMode(PLOT_TEXT_MODE aVal)
void SetSvgFitPageToBoard(int aSvgFitPageToBoard)
void SetSvgPrecision(unsigned aPrecision)
void SetCrossoutDNPFPsOnFabLayers(bool aFlag)
void SetFormat(PLOT_FORMAT aFormat)
void SetFineScaleAdjustY(double aVal)
void SetWidthAdjust(int aVal)
The backing store for a PROJECT, in JSON format.
wxString m_PcbLastPath[LAST_PATH_SIZE]
MRU path storage.
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
A bitmap button widget that behaves like a standard dialog button except with an icon.
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
T * GetTool()
Return the tool of given type or nullptr if there is no such tool registered.
Handle actions specific to filling copper zones.
A type-safe container of any type.
Definition ki_any.h:92
wxString ExpandPathVariables(const wxString &aPath, const PROJECT *aProject, const std::function< bool(wxString *)> *aTextResolver)
Expand text variables, environment variables and a leading '~' in a user-entered file path.
Definition common.cpp:798
wxString ResolveProjectPath(const wxString &aPath, const PROJECT *aProject, const std::function< bool(wxString *)> *aTextResolver)
Expand a user-entered file path as ExpandPathVariables() does, then anchor a relative result at the p...
Definition common.cpp:817
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:829
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:245
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
#define ID_STACKUP_ORDER
static bool setDouble(double *aResult, double aValue, double aMin, double aMax)
static bool setInt(int *aResult, int aValue, int aMin, int aMax)
PCB_LAYER_ID_CLIENT_DATA * getLayerClientData(const wxRearrangeList *aList, int aIdx)
#define ID_SELECT_ALL_LAYERS
static double selectionToScale(int selection)
#define ID_DESELECT_COPPER_LAYERS
#define ID_DESELECT_ALL_LAYERS
#define ID_LAYER_FAB
#define ID_SELECT_COPPER_LAYERS
#define DLG_WINDOW_NAME
Definition dialog_plot.h:26
#define _(s)
Classes used to generate a Gerber job file in JSON.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition idf_helpers.h:37
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:741
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ F_CrtYd
Definition layer_ids.h:112
@ F_Fab
Definition layer_ids.h:115
@ B_CrtYd
Definition layer_ids.h:111
@ UNDEFINED_LAYER
Definition layer_ids.h:57
This file contains miscellaneous commonly used macros and functions.
KICOMMON_API wxString StringFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Return the string from aValue according to aUnits (inch, mm ...) for display.
KICOMMON_API wxSize GetTextSize(const wxString &aSingleLine, wxWindow *aWindow)
Return the size of aSingleLine of text when it is rendered in aWindow using whatever font is currentl...
Definition ui_common.cpp:80
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:96
#define PLOT_MIN_SCALE
Definition pcbplot.h:55
#define PLOT_MAX_SCALE
Definition pcbplot.h:56
see class PGM_BASE
DRILL_MARKS
Plots and prints can show holes in pads and vias 3 options are available:
@ SKETCH
Definition plotter.h:83
PLOT_FORMAT
The set of supported output plot formats.
Definition plotter.h:65
Plotting engines similar to ps (PostScript, Gerber, svg)
@ LAST_PATH_PLOT
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_EXCLUSION
@ RPT_SEVERITY_INFO
#define DEFAULT_THEME
COLOR_SETTINGS * GetColorSettings(const wxString &aName)
T * GetAppSettings(const char *aFilename)
std::string path
IbisParser parser & reporter
Definition of file extensions used in Kicad.