KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcbnew_jobs_handler.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) 2022 Mark Roszko <[email protected]>
5 * Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <wx/dir.h>
22#include "pcbnew_jobs_handler.h"
23#include <board_commit.h>
25#include <drc/drc_item.h>
26#include <drc/drc_report.h>
30#include <jobs/job_fp_upgrade.h>
41#include <jobs/job_pcb_render.h>
42#include <jobs/job_pcb_drc.h>
43#include <lset.h>
44#include <cli/exit_codes.h>
50#include <tool/tool_manager.h>
51#include <tools/drc_tool.h>
52#include <filename_resolver.h>
57#include <kiface_base.h>
58#include <macros.h>
59#include <pad.h>
60#include <pcb_marker.h>
64#include <kiface_ids.h>
67#include <pcbnew_settings.h>
68#include <pcbplot.h>
69#include <pgm_base.h>
72#include <project_pcb.h>
74#include <reporter.h>
76#include <export_vrml.h>
77#include <wx/wfstream.h>
78#include <wx/zipstrm.h>
85#include <dialogs/dialog_plot.h>
86
88
89
90#ifdef _WIN32
91#ifdef TRANSPARENT
92#undef TRANSPARENT
93#endif
94#endif
95
96
98 JOB_DISPATCHER( aKiway ),
99 m_cliBoard( nullptr )
100{
101 Register( "3d", std::bind( &PCBNEW_JOBS_HANDLER::JobExportStep, this, std::placeholders::_1 ),
102 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
103 {
104 JOB_EXPORT_PCB_3D* svgJob = dynamic_cast<JOB_EXPORT_PCB_3D*>( job );
105
106 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
107 aKiway->Player( FRAME_PCB_EDITOR, false ) );
108 DIALOG_EXPORT_STEP dlg( editFrame, aParent, "", svgJob );
109 dlg.ShowModal();
110
111 return dlg.GetReturnCode() == wxID_OK;
112 } );
113 Register( "render",
114 std::bind( &PCBNEW_JOBS_HANDLER::JobExportRender, this, std::placeholders::_1 ),
115 []( JOB* job, wxWindow* aParent ) -> bool
116 {
117 return false;
118 } );
119 Register( "svg", std::bind( &PCBNEW_JOBS_HANDLER::JobExportSvg, this, std::placeholders::_1 ),
120 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
121 {
122 JOB_EXPORT_PCB_SVG* svgJob = dynamic_cast<JOB_EXPORT_PCB_SVG*>( job );
123
124 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
125 aKiway->Player( FRAME_PCB_EDITOR, false ) );
126 DIALOG_EXPORT_SVG dlg( svgJob, editFrame, aParent );
127 dlg.ShowModal();
128
129 return dlg.GetReturnCode() == wxID_OK;
130 } );
131 Register( "gencad",
132 std::bind( &PCBNEW_JOBS_HANDLER::JobExportGencad, this, std::placeholders::_1 ),
133 []( JOB* job, wxWindow* aParent ) -> bool
134 {
135 return false;
136 } );
137 Register( "dxf", std::bind( &PCBNEW_JOBS_HANDLER::JobExportDxf, this, std::placeholders::_1 ),
138 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
139 {
140 JOB_EXPORT_PCB_DXF* dxfJob = dynamic_cast<JOB_EXPORT_PCB_DXF*>( job );
141
142 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
143 aKiway->Player( FRAME_PCB_EDITOR, false ) );
144
145 DIALOG_PLOT dlg( editFrame, aParent, dxfJob );
146 dlg.ShowModal();
147
148 return dlg.GetReturnCode() == wxID_OK;
149 } );
150 Register( "pdf", std::bind( &PCBNEW_JOBS_HANDLER::JobExportPdf, this, std::placeholders::_1 ),
151 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
152 {
153 JOB_EXPORT_PCB_PDF* pdfJob = dynamic_cast<JOB_EXPORT_PCB_PDF*>( job );
154
155 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
156 aKiway->Player( FRAME_PCB_EDITOR, false ) );
157
158 DIALOG_PLOT dlg( editFrame, aParent, pdfJob );
159 dlg.ShowModal();
160
161 return dlg.GetReturnCode() == wxID_OK;
162 } );
163 Register( "gerber",
164 std::bind( &PCBNEW_JOBS_HANDLER::JobExportGerber, this, std::placeholders::_1 ),
165 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
166 {
167 JOB_EXPORT_PCB_GERBER* gJob = dynamic_cast<JOB_EXPORT_PCB_GERBER*>( job );
168
169 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
170 aKiway->Player( FRAME_PCB_EDITOR, false ) );
171
172 DIALOG_PLOT dlg( editFrame, aParent, gJob );
173 dlg.ShowModal();
174
175 return dlg.GetReturnCode() == wxID_OK;
176 } );
177 Register( "gerbers",
178 std::bind( &PCBNEW_JOBS_HANDLER::JobExportGerbers, this, std::placeholders::_1 ),
179 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
180 {
181 JOB_EXPORT_PCB_GERBERS* gJob = dynamic_cast<JOB_EXPORT_PCB_GERBERS*>( job );
182
183 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
184 aKiway->Player( FRAME_PCB_EDITOR, false ) );
185
186 DIALOG_PLOT dlg( editFrame, aParent, gJob );
187 dlg.ShowModal();
188
189 return dlg.GetReturnCode() == wxID_OK;
190 } );
191 Register( "drill",
192 std::bind( &PCBNEW_JOBS_HANDLER::JobExportDrill, this, std::placeholders::_1 ),
193 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
194 {
195 JOB_EXPORT_PCB_DRILL* drillJob = dynamic_cast<JOB_EXPORT_PCB_DRILL*>( job );
196
197 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( aKiway->Player( FRAME_PCB_EDITOR, false ) );
198 DIALOG_GENDRILL dlg( editFrame, drillJob, aParent );
199 dlg.ShowModal();
200 return dlg.GetReturnCode() == wxID_OK;
201 } );
202 Register( "pos", std::bind( &PCBNEW_JOBS_HANDLER::JobExportPos, this, std::placeholders::_1 ),
203 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
204 {
205 JOB_EXPORT_PCB_POS* posJob = dynamic_cast<JOB_EXPORT_PCB_POS*>( job );
206
207 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( aKiway->Player( FRAME_PCB_EDITOR, false ) );
208 DIALOG_GEN_FOOTPRINT_POSITION dlg( posJob, editFrame, aParent );
209 dlg.ShowModal();
210 return dlg.GetReturnCode() == wxID_OK;
211 } );
212 Register( "fpupgrade",
213 std::bind( &PCBNEW_JOBS_HANDLER::JobExportFpUpgrade, this, std::placeholders::_1 ),
214 []( JOB* job, wxWindow* aParent ) -> bool
215 {
216 return false;
217 } );
218 Register( "fpsvg",
219 std::bind( &PCBNEW_JOBS_HANDLER::JobExportFpSvg, this, std::placeholders::_1 ),
220 []( JOB* job, wxWindow* aParent ) -> bool
221 {
222 return false;
223 } );
224 Register( "drc", std::bind( &PCBNEW_JOBS_HANDLER::JobExportDrc, this, std::placeholders::_1 ),
225 []( JOB* job, wxWindow* aParent ) -> bool
226 {
227 return false;
228 } );
229 Register( "ipc2581",
230 std::bind( &PCBNEW_JOBS_HANDLER::JobExportIpc2581, this, std::placeholders::_1 ),
231 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
232 {
233 JOB_EXPORT_PCB_IPC2581* ipcJob = dynamic_cast<JOB_EXPORT_PCB_IPC2581*>( job );
234
235 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( aKiway->Player( FRAME_PCB_EDITOR, false ) );
236
237 DIALOG_EXPORT_2581 dlg( ipcJob, editFrame, aParent );
238 dlg.ShowModal();
239
240 return dlg.GetReturnCode() == wxID_OK;
241 } );
242}
243
244
245BOARD* PCBNEW_JOBS_HANDLER::getBoard( const wxString& aPath )
246{
247 BOARD* brd = nullptr;
248
249 if( !Pgm().IsGUI() &&
250 Pgm().GetSettingsManager().IsProjectOpen() )
251 {
253
254 wxString pcbPath = aPath;
255 if( pcbPath.IsEmpty() )
256 {
257 wxFileName path = project.GetProjectFullName();
259 path.MakeAbsolute();
260 pcbPath = path.GetFullPath();
261 }
262
263 if( !m_cliBoard )
264 {
265 m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
266 m_cliBoard = LoadBoard( pcbPath, true, &project );
267 }
268
269 brd = m_cliBoard;
270 }
271 else
272 {
273 m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
274 brd = LoadBoard( aPath, true, &Pgm().GetSettingsManager().Prj() );
275 }
276
277 if ( !brd )
278 {
279 m_reporter->Report( _( "Failed to load board\n" ), RPT_SEVERITY_ERROR );
280 }
281
282 return brd;
283}
284
285
287{
288 JOB_EXPORT_PCB_3D* aStepJob = dynamic_cast<JOB_EXPORT_PCB_3D*>( aJob );
289
290 if( aStepJob == nullptr )
292
293 BOARD* brd = getBoard( aStepJob->m_filename );
294
295 if( !brd )
297
298 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
300
301 if( aStepJob->GetOutputPath().IsEmpty() )
302 {
303 wxFileName fn = brd->GetFileName();
304 fn.SetName( fn.GetName() );
305
306 switch( aStepJob->m_format )
307 {
309 break;
311 break;
313 break;
315 break;
317 break;
318 default:
319 return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here
320 }
321
322 aStepJob->SetOutputPath( fn.GetFullName() );
323 }
324
326 {
327
328 double scale = 0.0;
329 switch ( aStepJob->m_vrmlUnits )
330 {
332 case JOB_EXPORT_PCB_3D::VRML_UNITS::METERS: scale = 0.001; break;
333 case JOB_EXPORT_PCB_3D::VRML_UNITS::TENTHS: scale = 10.0 / 25.4; break;
334 case JOB_EXPORT_PCB_3D::VRML_UNITS::INCHES: scale = 1.0 / 25.4; break;
335 }
336
337 EXPORTER_VRML vrmlExporter( brd );
338 wxString messages;
339
340 double originX = pcbIUScale.IUTomm( aStepJob->m_3dparams.m_Origin.x );
341 double originY = pcbIUScale.IUTomm( aStepJob->m_3dparams.m_Origin.y );
342
343 if( !aStepJob->m_hasUserOrigin )
344 {
345 BOX2I bbox = brd->ComputeBoundingBox( true );
346 originX = pcbIUScale.IUTomm( bbox.GetCenter().x );
347 originY = pcbIUScale.IUTomm( bbox.GetCenter().y );
348 }
349
350 bool success = vrmlExporter.ExportVRML_File(
351 brd->GetProject(), &messages, aStepJob->GetFullOutputPath(), scale,
353 !aStepJob->m_vrmlModelDir.IsEmpty(), aStepJob->m_vrmlRelativePaths,
354 aStepJob->m_vrmlModelDir, originX, originY );
355
356 if ( success )
357 {
358 m_reporter->Report( wxString::Format( _( "Successfully exported VRML to %s" ),
359 aStepJob->GetFullOutputPath() ),
361 }
362 else
363 {
364 m_reporter->Report( _( "Error exporting VRML" ), RPT_SEVERITY_ERROR );
366 }
367 }
368 else
369 {
370 EXPORTER_STEP_PARAMS params = aStepJob->m_3dparams;
371
372 switch( aStepJob->m_format )
373 {
376 break;
379 break;
382 break;
385 break;
386 default:
387 return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here
388 }
389
390 EXPORTER_STEP stepExporter( brd, params );
391 stepExporter.m_outputFile = aStepJob->GetFullOutputPath();
392
393 if( !stepExporter.Export() )
395 }
396
397 return CLI::EXIT_CODES::OK;
398}
399
400
402{
403 JOB_PCB_RENDER* aRenderJob = dynamic_cast<JOB_PCB_RENDER*>( aJob );
404
405 if( aRenderJob == nullptr )
407
408 BOARD* brd = getBoard( aRenderJob->m_filename );
409
410 if( !brd )
412
413 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
415
416 BOARD_ADAPTER boardAdapter;
417
418 boardAdapter.SetBoard( brd );
419 boardAdapter.m_IsBoardView = false;
420 boardAdapter.m_IsPreviewer =
421 true; // Force display 3D models, regardless the 3D viewer options
422
425
426 if( aRenderJob->m_quality == JOB_PCB_RENDER::QUALITY::BASIC )
427 {
428 // Silkscreen is pixelated without antialiasing
430
431 cfg->m_Render.raytrace_backfloor = false;
433
435 cfg->m_Render.raytrace_reflections = false;
436 cfg->m_Render.raytrace_shadows = false;
437
438 // Better colors
440
441 // Tracks below soldermask are not visible without refractions
442 cfg->m_Render.raytrace_refractions = true;
444 }
445 else if( aRenderJob->m_quality == JOB_PCB_RENDER::QUALITY::HIGH )
446 {
448 cfg->m_Render.raytrace_backfloor = true;
451 cfg->m_Render.raytrace_reflections = true;
452 cfg->m_Render.raytrace_shadows = true;
453 cfg->m_Render.raytrace_refractions = true;
455 }
456
457 if( aRenderJob->m_floor )
458 {
459 cfg->m_Render.raytrace_backfloor = true;
460 cfg->m_Render.raytrace_shadows = true;
462 }
463
464 cfg->m_CurrentPreset = aRenderJob->m_colorPreset;
465 boardAdapter.m_Cfg = cfg;
466
469 && aRenderJob->m_format == JOB_PCB_RENDER::FORMAT::PNG ) )
470 {
471 boardAdapter.m_ColorOverrides[LAYER_3D_BACKGROUND_TOP] = COLOR4D( 1.0, 1.0, 1.0, 0.0 );
472 boardAdapter.m_ColorOverrides[LAYER_3D_BACKGROUND_BOTTOM] = COLOR4D( 1.0, 1.0, 1.0, 0.0 );
473 }
474
476
477 static std::map<JOB_PCB_RENDER::SIDE, VIEW3D_TYPE> s_viewCmdMap = {
478 { JOB_PCB_RENDER::SIDE::TOP, VIEW3D_TYPE::VIEW3D_TOP },
479 { JOB_PCB_RENDER::SIDE::BOTTOM, VIEW3D_TYPE::VIEW3D_BOTTOM },
480 { JOB_PCB_RENDER::SIDE::LEFT, VIEW3D_TYPE::VIEW3D_LEFT },
481 { JOB_PCB_RENDER::SIDE::RIGHT, VIEW3D_TYPE::VIEW3D_RIGHT },
482 { JOB_PCB_RENDER::SIDE::FRONT, VIEW3D_TYPE::VIEW3D_FRONT },
483 { JOB_PCB_RENDER::SIDE::BACK, VIEW3D_TYPE::VIEW3D_BACK },
484 };
485
486 PROJECTION_TYPE projection =
487 aRenderJob->m_perspective ? PROJECTION_TYPE::PERSPECTIVE : PROJECTION_TYPE::ORTHO;
488
489 wxSize windowSize( aRenderJob->m_width, aRenderJob->m_height );
490 TRACK_BALL camera( 2 * RANGE_SCALE_3D );
491
492 camera.SetProjection( projection );
493 camera.SetCurWindowSize( windowSize );
494
495 RENDER_3D_RAYTRACE_RAM raytrace( boardAdapter, camera );
496 raytrace.SetCurWindowSize( windowSize );
497
498 for( bool first = true; raytrace.Redraw( false, m_reporter, m_reporter ); first = false )
499 {
500 if( first )
501 {
502 const float cmTo3D = boardAdapter.BiuTo3dUnits() * pcbIUScale.mmToIU( 10.0 );
503
504 // First redraw resets lookat point to the board center, so set up the camera here
505 camera.ViewCommand_T1( s_viewCmdMap[aRenderJob->m_side] );
506
507 camera.SetLookAtPos_T1(
508 camera.GetLookAtPos_T1()
509 + SFVEC3F( aRenderJob->m_pivot.x, aRenderJob->m_pivot.y, aRenderJob->m_pivot.z )
510 * cmTo3D );
511
512 camera.Pan_T1(
513 SFVEC3F( aRenderJob->m_pan.x, aRenderJob->m_pan.y, aRenderJob->m_pan.z ) );
514
515 camera.Zoom_T1( aRenderJob->m_zoom );
516
517 camera.RotateX_T1( DEG2RAD( aRenderJob->m_rotation.x ) );
518 camera.RotateY_T1( DEG2RAD( aRenderJob->m_rotation.y ) );
519 camera.RotateZ_T1( DEG2RAD( aRenderJob->m_rotation.z ) );
520
521 camera.Interpolate( 1.0f );
522 camera.SetT0_and_T1_current_T();
523 camera.ParametersChanged();
524 }
525 }
526
527 uint8_t* rgbaBuffer = raytrace.GetBuffer();
528 wxSize realSize = raytrace.GetRealBufferSize();
529 bool success = !!rgbaBuffer;
530
531 if( rgbaBuffer )
532 {
533 const unsigned int wxh = realSize.x * realSize.y;
534
535 unsigned char* rgbBuffer = (unsigned char*) malloc( wxh * 3 );
536 unsigned char* alphaBuffer = (unsigned char*) malloc( wxh );
537
538 unsigned char* rgbaPtr = rgbaBuffer;
539 unsigned char* rgbPtr = rgbBuffer;
540 unsigned char* alphaPtr = alphaBuffer;
541
542 for( int y = 0; y < realSize.y; y++ )
543 {
544 for( int x = 0; x < realSize.x; x++ )
545 {
546 rgbPtr[0] = rgbaPtr[0];
547 rgbPtr[1] = rgbaPtr[1];
548 rgbPtr[2] = rgbaPtr[2];
549 alphaPtr[0] = rgbaPtr[3];
550
551 rgbaPtr += 4;
552 rgbPtr += 3;
553 alphaPtr += 1;
554 }
555 }
556
557 wxImage image( realSize );
558 image.SetData( rgbBuffer );
559 image.SetAlpha( alphaBuffer );
560 image = image.Mirror( false );
561
562 image.SetOption( wxIMAGE_OPTION_QUALITY, 90 );
563 image.SaveFile( aRenderJob->m_outputFile,
564 aRenderJob->m_format == JOB_PCB_RENDER::FORMAT::PNG ? wxBITMAP_TYPE_PNG
565 : wxBITMAP_TYPE_JPEG );
566 }
567
568 m_reporter->Report( wxString::Format( _( "Actual image size: %dx%d" ), realSize.x, realSize.y )
569 + wxS( "\n" ),
571
572 if( success )
573 m_reporter->Report( _( "Successfully created 3D render image" ) + wxS( "\n" ),
575 else
576 m_reporter->Report( _( "Error creating 3D render image" ) + wxS( "\n" ),
578
579 return CLI::EXIT_CODES::OK;
580}
581
582
584{
585 JOB_EXPORT_PCB_SVG* aSvgJob = dynamic_cast<JOB_EXPORT_PCB_SVG*>( aJob );
586
587 if( aSvgJob == nullptr )
589
590 PCB_PLOT_SVG_OPTIONS svgPlotOptions;
591 svgPlotOptions.m_blackAndWhite = aSvgJob->m_blackAndWhite;
592 svgPlotOptions.m_colorTheme = aSvgJob->m_colorTheme;
593 svgPlotOptions.m_outputFile = aSvgJob->GetFullOutputPath();
594 svgPlotOptions.m_mirror = aSvgJob->m_mirror;
595 svgPlotOptions.m_negative = aSvgJob->m_negative;
596 svgPlotOptions.m_pageSizeMode = aSvgJob->m_pageSizeMode;
597 svgPlotOptions.m_printMaskLayer = aSvgJob->m_printMaskLayer;
598 svgPlotOptions.m_plotFrame = aSvgJob->m_plotDrawingSheet;
599 svgPlotOptions.m_sketchPadsOnFabLayers = aSvgJob->m_sketchPadsOnFabLayers;
600 svgPlotOptions.m_hideDNPFPsOnFabLayers = aSvgJob->m_hideDNPFPsOnFabLayers;
603 svgPlotOptions.m_drillShapeOption = aSvgJob->m_drillShapeOption;
604
605 BOARD* brd = getBoard( aSvgJob->m_filename );
606
607 if( !brd )
609
611 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
613
614 if( aJob->IsCli() )
615 {
616 if( EXPORT_SVG::Plot( brd, svgPlotOptions ) )
617 m_reporter->Report( _( "Successfully created svg file" ) + wxS( "\n" ), RPT_SEVERITY_INFO );
618 else
619 m_reporter->Report( _( "Error creating svg file" ) + wxS( "\n" ), RPT_SEVERITY_ERROR );
620 }
621
622 return CLI::EXIT_CODES::OK;
623}
624
625
627{
628 JOB_EXPORT_PCB_DXF* aDxfJob = dynamic_cast<JOB_EXPORT_PCB_DXF*>( aJob );
629
630 if( aDxfJob == nullptr )
632
633 BOARD* brd = getBoard( aDxfJob->m_filename );
634
635 if( !brd )
637
639 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
641
642 if( aDxfJob->GetOutputPath().IsEmpty() )
643 {
644 wxFileName fn = brd->GetFileName();
645 fn.SetName( fn.GetName() );
646 fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::DXF ) );
647
648 aDxfJob->SetOutputPath( fn.GetFullName() );
649 }
650
651 PCB_PLOT_PARAMS plotOpts;
652 plotOpts.SetFormat( PLOT_FORMAT::DXF );
653
655 plotOpts.SetUseAuxOrigin( aDxfJob->m_useDrillOrigin );
656
658 plotOpts.SetDXFPlotUnits( DXF_UNITS::MILLIMETERS );
659 else
660 plotOpts.SetDXFPlotUnits( DXF_UNITS::INCHES );
661
662 plotOpts.SetPlotFrameRef( aDxfJob->m_plotDrawingSheet );
663 plotOpts.SetPlotValue( aDxfJob->m_plotFootprintValues );
664 plotOpts.SetPlotReference( aDxfJob->m_plotRefDes );
665 plotOpts.SetLayerSelection( aDxfJob->m_printMaskLayer );
666
668 wxString layerName;
669 wxString sheetName;
670 wxString sheetPath;
671
672 if( aDxfJob->m_printMaskLayer.size() == 1 )
673 {
674 layer = aDxfJob->m_printMaskLayer.front();
675 layerName = brd->GetLayerName( layer );
676 }
677
678 if( aJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
679 layerName = aJob->GetVarOverrides().at( wxT( "LAYER" ) );
680
681 if( aJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
682 sheetName = aJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
683
684 if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
685 sheetPath = aJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
686
687 DXF_PLOTTER* plotter = (DXF_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer, layerName, aDxfJob->GetFullOutputPath(), sheetName,
688 sheetPath );
689
690 if( plotter )
691 {
692 PlotBoardLayers( brd, plotter, aDxfJob->m_printMaskLayer, plotOpts );
693 plotter->EndPlot();
694 }
695
696 delete plotter;
697
698 return CLI::EXIT_CODES::OK;
699}
700
701
703{
704 JOB_EXPORT_PCB_PDF* aPdfJob = dynamic_cast<JOB_EXPORT_PCB_PDF*>( aJob );
705
706 if( aPdfJob == nullptr )
708
709 BOARD* brd = getBoard( aPdfJob->m_filename );
710
711 if( !brd )
713
715 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
717
718 if( aPdfJob->OutputPathFullSpecified() )
719 {
720 wxFileName fn = brd->GetFileName();
721 fn.SetName( fn.GetName() );
722 fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::PDF ) );
723
724 aPdfJob->SetOutputPath( fn.GetFullName() );
725 }
726
727 PCB_PLOT_PARAMS plotOpts;
728 plotOpts.SetFormat( PLOT_FORMAT::PDF );
729
730 plotOpts.SetPlotFrameRef( aPdfJob->m_plotDrawingSheet );
731 plotOpts.SetPlotValue( aPdfJob->m_plotFootprintValues );
732 plotOpts.SetPlotReference( aPdfJob->m_plotRefDes );
733
734 plotOpts.SetLayerSelection( aPdfJob->m_printMaskLayer );
735
737 plotOpts.SetColorSettings( mgr.GetColorSettings( aPdfJob->m_colorTheme ) );
738 plotOpts.SetMirror( aPdfJob->m_mirror );
739 plotOpts.SetBlackAndWhite( aPdfJob->m_blackAndWhite );
740 plotOpts.SetNegative( aPdfJob->m_negative );
741
742 if( aPdfJob->m_sketchPadsOnFabLayers )
743 {
744 plotOpts.SetSketchPadsOnFabLayers( true );
745 plotOpts.SetPlotPadNumbers( true );
746 }
747
751
752 switch( aPdfJob->m_drillShapeOption )
753 {
754 default:
755 case 0: plotOpts.SetDrillMarksType( DRILL_MARKS::NO_DRILL_SHAPE ); break;
756 case 1: plotOpts.SetDrillMarksType( DRILL_MARKS::SMALL_DRILL_SHAPE ); break;
757 case 2: plotOpts.SetDrillMarksType( DRILL_MARKS::FULL_DRILL_SHAPE ); break;
758 }
759
761 wxString layerName;
762 wxString sheetName;
763 wxString sheetPath;
764
765 if( aPdfJob->m_printMaskLayer.size() == 1 )
766 {
767 layer = aPdfJob->m_printMaskLayer.front();
768 layerName = brd->GetLayerName( layer );
769 }
770
771 if( aPdfJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
772 layerName = aPdfJob->GetVarOverrides().at( wxT( "LAYER" ) );
773
774 if( aPdfJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
775 sheetName = aPdfJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
776
777 if( aPdfJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
778 sheetPath = aPdfJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
779
780 PDF_PLOTTER* plotter = (PDF_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer, layerName, aPdfJob->GetFullOutputPath(), sheetName,
781 sheetPath );
782
783 if( plotter )
784 {
785 PlotBoardLayers( brd, plotter, aPdfJob->m_printMaskLayer, plotOpts );
786 PlotInteractiveLayer( brd, plotter, plotOpts );
787 plotter->EndPlot();
788 }
789
790 delete plotter;
791
792 return CLI::EXIT_CODES::OK;
793}
794
795
797{
798 int exitCode = CLI::EXIT_CODES::OK;
799 JOB_EXPORT_PCB_GERBERS* aGerberJob = dynamic_cast<JOB_EXPORT_PCB_GERBERS*>( aJob );
800
801 if( aGerberJob == nullptr )
803
804 BOARD* brd = getBoard( aGerberJob->m_filename );
805
806 if( !brd )
808
809 loadOverrideDrawingSheet( brd, aGerberJob->m_drawingSheet );
810 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
812
813 PCB_PLOT_PARAMS boardPlotOptions = brd->GetPlotOptions();
814 LSET plotOnAllLayersSelection = boardPlotOptions.GetPlotOnAllLayersSelection();
815 GERBER_JOBFILE_WRITER jobfile_writer( brd );
816
817 wxString fileExt;
818
819 if( aGerberJob->m_useBoardPlotParams )
820 {
821 // The board plot options are saved with all copper layers enabled, even those that don't
822 // exist in the current stackup. This is done so the layers are automatically enabled in the plot
823 // dialog when the user enables them. We need to filter out these not-enabled layers here so
824 // we don't plot 32 layers when we only have 4, etc.
825 LSET plotLayers = ( boardPlotOptions.GetLayerSelection() & LSET::AllNonCuMask() )
826 | ( brd->GetEnabledLayers() & LSET::AllCuMask() );
827 aGerberJob->m_printMaskLayer = plotLayers.SeqStackupForPlotting();
828 aGerberJob->m_layersIncludeOnAll = boardPlotOptions.GetPlotOnAllLayersSelection();
829 }
830 else
831 {
832 // default to the board enabled layers
833 if( aGerberJob->m_printMaskLayer.empty() )
835
836 if( aGerberJob->m_layersIncludeOnAllSet )
837 aGerberJob->m_layersIncludeOnAll = plotOnAllLayersSelection;
838 }
839
840 // Ensure layers to plot are restricted to enabled layers of the board to plot
841 LSET layersToPlot = LSET( { aGerberJob->m_printMaskLayer } ) & brd->GetEnabledLayers();
842
843 for( PCB_LAYER_ID layer : layersToPlot.UIOrder() )
844 {
845 LSEQ plotSequence;
846
847 // Base layer always gets plotted first.
848 plotSequence.push_back( layer );
849
850 // Now all the "include on all" layers
851 for( PCB_LAYER_ID layer_all : aGerberJob->m_layersIncludeOnAll.UIOrder() )
852 {
853 // Don't plot the same layer more than once;
854 if( find( plotSequence.begin(), plotSequence.end(), layer_all ) != plotSequence.end() )
855 continue;
856
857 plotSequence.push_back( layer_all );
858 }
859
860 // Pick the basename from the board file
861 wxFileName fn( brd->GetFileName() );
862 wxString layerName = brd->GetLayerName( layer );
863 wxString sheetName;
864 wxString sheetPath;
865 PCB_PLOT_PARAMS plotOpts;
866
867 if( aGerberJob->m_useBoardPlotParams )
868 plotOpts = boardPlotOptions;
869 else
870 populateGerberPlotOptionsFromJob( plotOpts, aGerberJob );
871
872 if( plotOpts.GetUseGerberProtelExtensions() )
873 fileExt = GetGerberProtelExtension( layer );
874 else
876
877 BuildPlotFileName( &fn, aGerberJob->GetFullOutputPath(), layerName, fileExt );
878 wxString fullname = fn.GetFullName();
879
880 jobfile_writer.AddGbrFile( layer, fullname );
881
882 if( aJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
883 layerName = aJob->GetVarOverrides().at( wxT( "LAYER" ) );
884
885 if( aJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
886 sheetName = aJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
887
888 if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
889 sheetPath = aJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
890
891 // We are feeding it one layer at the start here to silence a logic check
892 GERBER_PLOTTER* plotter = (GERBER_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer,
893 layerName, fn.GetFullPath(),
894 sheetName, sheetPath );
895
896 if( plotter )
897 {
898 m_reporter->Report( wxString::Format( _( "Plotted to '%s'.\n" ), fn.GetFullPath() ),
900 PlotBoardLayers( brd, plotter, plotSequence, plotOpts );
901 plotter->EndPlot();
902 }
903 else
904 {
905 m_reporter->Report( wxString::Format( _( "Failed to plot to '%s'.\n" ),
906 fn.GetFullPath() ),
909 }
910
911 delete plotter;
912 }
913
914 wxFileName fn( aGerberJob->m_filename );
915
916 // Build gerber job file from basename
917 BuildPlotFileName( &fn, aGerberJob->GetFullOutputPath(), wxT( "job" ),
919 jobfile_writer.CreateJobFile( fn.GetFullPath() );
920
921 return exitCode;
922}
923
925{
926 JOB_EXPORT_PCB_GENCAD* aGencadJob = dynamic_cast<JOB_EXPORT_PCB_GENCAD*>( aJob );
927
928 if( aGencadJob == nullptr )
930
931 BOARD* aBoard = LoadBoard( aGencadJob->m_filename, true ); // Ensure m_board is of type BOARD*
932
933 if( aBoard == nullptr )
935
936 GENCAD_EXPORTER exporter( aBoard );
937
938 VECTOR2I GencadOffset;
939 VECTOR2I auxOrigin = aBoard->GetDesignSettings().GetAuxOrigin();
940 GencadOffset.x = aGencadJob->m_useDrillOrigin ? auxOrigin.x : 0;
941 GencadOffset.y = aGencadJob->m_useDrillOrigin ? auxOrigin.y : 0;
942
943 exporter.FlipBottomPads( aGencadJob->m_flipBottomPads );
944 exporter.UsePinNamesUnique( aGencadJob->m_useUniquePins );
945 exporter.UseIndividualShapes( aGencadJob->m_useIndividualShapes );
946 exporter.SetPlotOffet( GencadOffset );
947 exporter.StoreOriginCoordsInFile( aGencadJob->m_storeOriginCoords );
948
949 if( aGencadJob->GetOutputPath().IsEmpty() )
950 {
951 wxFileName fn = aBoard->GetFileName();
952 fn.SetName( fn.GetName() );
953 fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::DXF ) );
954
955 aGencadJob->SetOutputPath( fn.GetFullName() );
956 }
957
958 if( !exporter.WriteFile( aGencadJob->GetFullOutputPath() ) )
959 {
960 wxString msg;
961 msg.Printf( _( "Failed to create file '%s'.\n" ), aGencadJob->GetFullOutputPath() );
962
963 if( aJob->IsCli() )
965
967 }
968
969 if( aJob->IsCli() )
970 m_reporter->Report( _( "Successfully created genCAD file\n" ), RPT_SEVERITY_INFO );
971
972 return CLI::EXIT_CODES::OK;
973}
974
975
978{
979 aPlotOpts.SetFormat( PLOT_FORMAT::GERBER );
980
981 aPlotOpts.SetPlotFrameRef( aJob->m_plotDrawingSheet );
982 aPlotOpts.SetPlotValue( aJob->m_plotFootprintValues );
983 aPlotOpts.SetPlotReference( aJob->m_plotRefDes );
984
986
987 // Always disable plot pad holes
988 aPlotOpts.SetDrillMarksType( DRILL_MARKS::NO_DRILL_SHAPE );
989
991 aPlotOpts.SetUseGerberX2format( aJob->m_useX2Format );
993 aPlotOpts.SetUseAuxOrigin( aJob->m_useAuxOrigin );
995 aPlotOpts.SetGerberPrecision( aJob->m_precision );
996}
997
998
1000{
1001 int exitCode = CLI::EXIT_CODES::OK;
1002 JOB_EXPORT_PCB_GERBER* aGerberJob = dynamic_cast<JOB_EXPORT_PCB_GERBER*>( aJob );
1003
1004 if( aGerberJob == nullptr )
1006
1007 BOARD* brd = getBoard( aGerberJob->m_filename );
1008
1009 if( !brd )
1011
1012 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
1013 brd->SynchronizeProperties();
1014
1015 if( aGerberJob->GetOutputPath().IsEmpty() )
1016 {
1017 wxFileName fn = brd->GetFileName();
1018 fn.SetName( fn.GetName() );
1019 fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::GERBER ) );
1020
1021 aGerberJob->SetOutputPath( fn.GetFullName() );
1022 }
1023
1024 PCB_PLOT_PARAMS plotOpts;
1025 populateGerberPlotOptionsFromJob( plotOpts, aGerberJob );
1026 plotOpts.SetLayerSelection( aGerberJob->m_printMaskLayer );
1027
1029 wxString layerName;
1030 wxString sheetName;
1031 wxString sheetPath;
1032
1033 if( aGerberJob->m_printMaskLayer.size() == 1 )
1034 {
1035 layer = aGerberJob->m_printMaskLayer.front();
1036 layerName = brd->GetLayerName( layer );
1037 }
1038
1039 if( aJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
1040 layerName = aJob->GetVarOverrides().at( wxT( "LAYER" ) );
1041
1042 if( aJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
1043 sheetName = aJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
1044
1045 if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
1046 sheetPath = aJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
1047
1048 // We are feeding it one layer at the start here to silence a logic check
1049 GERBER_PLOTTER* plotter = (GERBER_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer, layerName,
1050 aGerberJob->GetFullOutputPath(),
1051 sheetName, sheetPath );
1052
1053 if( plotter )
1054 {
1055 PlotBoardLayers( brd, plotter, aGerberJob->m_printMaskLayer, plotOpts );
1056 plotter->EndPlot();
1057 }
1058 else
1059 {
1060 m_reporter->Report( wxString::Format( _( "Failed to plot to '%s'.\n" ),
1061 aGerberJob->GetFullOutputPath() ),
1064 }
1065
1066 delete plotter;
1067
1068 return exitCode;
1069}
1070
1073
1074
1076{
1077 JOB_EXPORT_PCB_DRILL* aDrillJob = dynamic_cast<JOB_EXPORT_PCB_DRILL*>( aJob );
1078
1079 if( aDrillJob == nullptr )
1081
1082 BOARD* brd = getBoard( aDrillJob->m_filename );
1083
1084 if( !brd )
1086
1087 // ensure output dir exists
1088 wxFileName fn( aDrillJob->GetFullOutputPath() + wxT( "/" ) );
1089
1090 if( !fn.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
1091 {
1092 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
1094 }
1095
1096 std::unique_ptr<GENDRILL_WRITER_BASE> drillWriter;
1097
1099 drillWriter = std::make_unique<EXCELLON_WRITER>( brd );
1100 else
1101 drillWriter = std::make_unique<GERBER_WRITER>( brd );
1102
1103 VECTOR2I offset;
1104
1106 offset = VECTOR2I( 0, 0 );
1107 else
1108 offset = brd->GetDesignSettings().GetAuxOrigin();
1109
1110 PLOT_FORMAT mapFormat = PLOT_FORMAT::PDF;
1111
1112 switch( aDrillJob->m_mapFormat )
1113 {
1114 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::POSTSCRIPT: mapFormat = PLOT_FORMAT::POST; break;
1115 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::GERBER_X2: mapFormat = PLOT_FORMAT::GERBER; break;
1116 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::DXF: mapFormat = PLOT_FORMAT::DXF; break;
1117 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::SVG: mapFormat = PLOT_FORMAT::SVG; break;
1118 default:
1119 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::PDF: mapFormat = PLOT_FORMAT::PDF; break;
1120 }
1121
1123 {
1125 switch( aDrillJob->m_zeroFormat )
1126 {
1129 break;
1132 break;
1135 break;
1137 default:
1139 break;
1140 }
1141
1142 DRILL_PRECISION precision;
1143
1145 precision = precisionListForInches;
1146 else
1147 precision = precisionListForMetric;
1148
1149 EXCELLON_WRITER* excellonWriter = dynamic_cast<EXCELLON_WRITER*>( drillWriter.get() );
1150
1151 if( excellonWriter == nullptr )
1153
1154 excellonWriter->SetFormat( aDrillJob->m_drillUnits
1156 zeroFmt, precision.m_Lhs, precision.m_Rhs );
1157 excellonWriter->SetOptions( aDrillJob->m_excellonMirrorY,
1158 aDrillJob->m_excellonMinimalHeader,
1159 offset, aDrillJob->m_excellonCombinePTHNPTH );
1160 excellonWriter->SetRouteModeForOvalHoles( aDrillJob->m_excellonOvalDrillRoute );
1161 excellonWriter->SetMapFileFormat( mapFormat );
1162
1163 if( !excellonWriter->CreateDrillandMapFilesSet( aDrillJob->GetFullOutputPath(), true,
1164 aDrillJob->m_generateMap, m_reporter ) )
1165 {
1167 }
1168 }
1170 {
1171 GERBER_WRITER* gerberWriter = dynamic_cast<GERBER_WRITER*>( drillWriter.get() );
1172
1173 if( gerberWriter == nullptr )
1175
1176 // Set gerber precision: only 5 or 6 digits for mantissa are allowed
1177 // (SetFormat() accept 5 or 6, and any other value set the precision to 5)
1178 // the integer part precision is always 4, and units always mm
1179 gerberWriter->SetFormat( aDrillJob->m_gerberPrecision );
1180 gerberWriter->SetOptions( offset );
1181 gerberWriter->SetMapFileFormat( mapFormat );
1182
1183 if( !gerberWriter->CreateDrillandMapFilesSet( aDrillJob->GetFullOutputPath(), true,
1184 aDrillJob->m_generateMap, m_reporter ) )
1185 {
1187 }
1188 }
1189
1190 return CLI::EXIT_CODES::OK;
1191}
1192
1193
1195{
1196 JOB_EXPORT_PCB_POS* aPosJob = dynamic_cast<JOB_EXPORT_PCB_POS*>( aJob );
1197
1198 if( aPosJob == nullptr )
1200
1201 BOARD* brd = getBoard( aPosJob->m_filename );
1202
1203 if( !brd )
1204 {
1206 }
1207
1208 if( aPosJob->GetOutputPath().IsEmpty() )
1209 {
1210 wxFileName fn = brd->GetFileName();
1211 fn.SetName( fn.GetName() );
1212
1215 else if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV )
1216 fn.SetExt( FILEEXT::CsvFileExtension );
1217 else if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::GERBER )
1218 fn.SetExt( FILEEXT::GerberFileExtension );
1219
1220 aPosJob->SetOutputPath( fn.GetFullName() );
1221 }
1222
1225 {
1226 FILE* file = nullptr;
1227 file = wxFopen( aPosJob->GetFullOutputPath(), wxS( "wt" ) );
1228
1229 if( file == nullptr )
1231
1232 std::string data;
1233
1234 bool frontSide = aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::FRONT
1236
1237 bool backSide = aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BACK
1239
1240 PLACE_FILE_EXPORTER exporter( brd,
1242 aPosJob->m_smdOnly, aPosJob->m_excludeFootprintsWithTh,
1243 aPosJob->m_excludeDNP,
1244 frontSide, backSide,
1247 aPosJob->m_negateBottomX );
1248 data = exporter.GenPositionData();
1249
1250 fputs( data.c_str(), file );
1251 fclose( file );
1252
1253 aPosJob->AddOutput( aPosJob->GetFullOutputPath() );
1254 }
1255 else if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::GERBER )
1256 {
1257 PLACEFILE_GERBER_WRITER exporter( brd );
1258
1259 PCB_LAYER_ID gbrLayer = F_Cu;
1260
1261 if( aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BACK )
1262 gbrLayer = B_Cu;
1263
1264 if( exporter.CreatePlaceFile( aPosJob->GetFullOutputPath(), gbrLayer, aPosJob->m_gerberBoardEdge )
1265 >= 0 )
1266 {
1267 aPosJob->AddOutput( aPosJob->GetFullOutputPath() );
1268 }
1269 else
1270 {
1272 }
1273 }
1274
1275 return CLI::EXIT_CODES::OK;
1276}
1277
1278extern FOOTPRINT* try_load_footprint( const wxFileName& aFileName, PCB_IO_MGR::PCB_FILE_T aFileType,
1279 const wxString& aName );
1280
1281
1283{
1284 JOB_FP_UPGRADE* upgradeJob = dynamic_cast<JOB_FP_UPGRADE*>( aJob );
1285
1286 if( upgradeJob == nullptr )
1288
1290
1291 if( !upgradeJob->m_outputLibraryPath.IsEmpty() )
1292 {
1293 if( wxFile::Exists( upgradeJob->m_outputLibraryPath ) ||
1294 wxDir::Exists( upgradeJob->m_outputLibraryPath) )
1295 {
1296 m_reporter->Report( _( "Output path must not conflict with existing path\n" ),
1299 }
1300 }
1301 else if( fileType != PCB_IO_MGR::KICAD_SEXP )
1302 {
1303 m_reporter->Report( _( "Output path must be specified to convert legacy and non-KiCad libraries\n" ),
1305
1307 }
1308
1310 {
1311 if( !wxDir::Exists( upgradeJob->m_libraryPath ) )
1312 {
1313 m_reporter->Report( _( "Footprint library path does not exist or is not accessible\n" ),
1316 }
1317
1318
1319 if( aJob->IsCli() )
1320 m_reporter->Report( _( "Loading footprint library\n" ), RPT_SEVERITY_INFO );
1321
1323 FP_CACHE fpLib( &pcb_io, upgradeJob->m_libraryPath );
1324
1325 try
1326 {
1327 fpLib.Load();
1328 }
1329 catch( ... )
1330 {
1331 m_reporter->Report( _( "Unable to load library\n" ), RPT_SEVERITY_ERROR );
1333 }
1334
1335 bool shouldSave = upgradeJob->m_force;
1336
1337 for( const auto& footprint : fpLib.GetFootprints() )
1338 {
1339 if( footprint.second->GetFootprint()->GetFileFormatVersionAtLoad()
1341 {
1342 shouldSave = true;
1343 }
1344 }
1345
1346 if( shouldSave )
1347 {
1348 m_reporter->Report( _( "Saving footprint library\n" ), RPT_SEVERITY_INFO );
1349
1350 try
1351 {
1352 if( !upgradeJob->m_outputLibraryPath.IsEmpty() )
1353 {
1354 fpLib.SetPath( upgradeJob->m_outputLibraryPath );
1355 }
1356
1357 fpLib.Save();
1358 }
1359 catch( ... )
1360 {
1361 m_reporter->Report( _( "Unable to save library\n" ), RPT_SEVERITY_ERROR );
1363 }
1364 }
1365 else
1366 {
1367 m_reporter->Report( _( "Footprint library was not updated\n" ), RPT_SEVERITY_INFO );
1368 }
1369 }
1370 else
1371 {
1372 if( !PCB_IO_MGR::ConvertLibrary( nullptr, upgradeJob->m_libraryPath,
1373 upgradeJob->m_outputLibraryPath, nullptr /* REPORTER */ ) )
1374 {
1375 m_reporter->Report( ( "Unable to convert library\n" ), RPT_SEVERITY_ERROR );
1377 }
1378 }
1379
1380 return CLI::EXIT_CODES::OK;
1381}
1382
1383
1385{
1386 JOB_FP_EXPORT_SVG* svgJob = dynamic_cast<JOB_FP_EXPORT_SVG*>( aJob );
1387
1388 if( svgJob == nullptr )
1390
1391 if( aJob->IsCli() )
1392 m_reporter->Report( _( "Loading footprint library\n" ), RPT_SEVERITY_INFO );
1393
1395 FP_CACHE fpLib( &pcb_io, svgJob->m_libraryPath );
1396
1397 try
1398 {
1399 fpLib.Load();
1400 }
1401 catch( ... )
1402 {
1403 m_reporter->Report( _( "Unable to load library\n" ), RPT_SEVERITY_ERROR );
1405 }
1406
1407 if( !svgJob->m_outputDirectory.IsEmpty() && !wxDir::Exists( svgJob->m_outputDirectory ) )
1408 {
1409 wxFileName::Mkdir( svgJob->m_outputDirectory );
1410 }
1411
1412 int exitCode = CLI::EXIT_CODES::OK;
1413
1414 // Just plot all the symbols we can
1415 FP_CACHE_FOOTPRINT_MAP& footprintMap = fpLib.GetFootprints();
1416
1417 bool singleFpPlotted = false;
1418 for( FP_CACHE_FOOTPRINT_MAP::iterator it = footprintMap.begin(); it != footprintMap.end();
1419 ++it )
1420 {
1421 const FOOTPRINT* fp = it->second->GetFootprint();
1422 if( !svgJob->m_footprint.IsEmpty() )
1423 {
1424 if( fp->GetFPID().GetLibItemName().wx_str() != svgJob->m_footprint )
1425 {
1426 // skip until we find the right footprint
1427 continue;
1428 }
1429 else
1430 {
1431 singleFpPlotted = true;
1432 }
1433 }
1434
1435 exitCode = doFpExportSvg( svgJob, fp );
1436 if( exitCode != CLI::EXIT_CODES::OK )
1437 break;
1438 }
1439
1440 if( !svgJob->m_footprint.IsEmpty() && !singleFpPlotted )
1441 {
1442 m_reporter->Report( _( "The given footprint could not be found to export." ) + wxS( "\n" ),
1444 }
1445
1446 return CLI::EXIT_CODES::OK;
1447}
1448
1449
1451{
1452 // the hack for now is we create fake boards containing the footprint and plot the board
1453 // until we refactor better plot api later
1454 std::unique_ptr<BOARD> brd;
1455 brd.reset( CreateEmptyBoard() );
1456 brd->GetProject()->ApplyTextVars( aSvgJob->GetVarOverrides() );
1457 brd->SynchronizeProperties();
1458
1459 FOOTPRINT* fp = dynamic_cast<FOOTPRINT*>( aFootprint->Clone() );
1460
1461 if( fp == nullptr )
1463
1464 fp->SetLink( niluuid );
1465 fp->SetFlags( IS_NEW );
1466 fp->SetParent( brd.get() );
1467
1468 for( PAD* pad : fp->Pads() )
1469 {
1470 pad->SetLocalRatsnestVisible( false );
1471 pad->SetNetCode( 0 );
1472 }
1473
1474 fp->SetOrientation( ANGLE_0 );
1475 fp->SetPosition( VECTOR2I( 0, 0 ) );
1476
1477 brd->Add( fp, ADD_MODE::INSERT, true );
1478
1479 wxFileName outputFile;
1480 outputFile.SetPath( aSvgJob->m_outputDirectory );
1481 outputFile.SetName( aFootprint->GetFPID().GetLibItemName().wx_str() );
1482 outputFile.SetExt( FILEEXT::SVGFileExtension );
1483
1484 m_reporter->Report( wxString::Format( _( "Plotting footprint '%s' to '%s'\n" ),
1485 aFootprint->GetFPID().GetLibItemName().wx_str(),
1486 outputFile.GetFullPath() ),
1488
1489
1490 PCB_PLOT_SVG_OPTIONS svgPlotOptions;
1491 svgPlotOptions.m_blackAndWhite = aSvgJob->m_blackAndWhite;
1492 svgPlotOptions.m_colorTheme = aSvgJob->m_colorTheme;
1493 svgPlotOptions.m_outputFile = outputFile.GetFullPath();
1494 svgPlotOptions.m_mirror = false;
1495 svgPlotOptions.m_pageSizeMode = 2; // board bounding box
1496 svgPlotOptions.m_printMaskLayer = aSvgJob->m_printMaskLayer;
1497 svgPlotOptions.m_sketchPadsOnFabLayers = aSvgJob->m_sketchPadsOnFabLayers;
1498 svgPlotOptions.m_hideDNPFPsOnFabLayers = aSvgJob->m_hideDNPFPsOnFabLayers;
1499 svgPlotOptions.m_sketchDNPFPsOnFabLayers = aSvgJob->m_sketchDNPFPsOnFabLayers;
1501 svgPlotOptions.m_plotFrame = false;
1502
1503 if( !EXPORT_SVG::Plot( brd.get(), svgPlotOptions ) )
1504 m_reporter->Report( _( "Error creating svg file" ) + wxS( "\n" ), RPT_SEVERITY_ERROR );
1505
1506 return CLI::EXIT_CODES::OK;
1507}
1508
1509
1511{
1512 JOB_PCB_DRC* drcJob = dynamic_cast<JOB_PCB_DRC*>( aJob );
1513
1514 if( drcJob == nullptr )
1516
1517 BOARD* brd = getBoard( drcJob->m_filename );
1518
1519 if( !brd )
1521
1522 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
1523 brd->SynchronizeProperties();
1524
1525 if( drcJob->m_outputFile.IsEmpty() )
1526 {
1527 wxFileName fn = brd->GetFileName();
1528 fn.SetName( fn.GetName() );
1529
1531 fn.SetExt( FILEEXT::JsonFileExtension );
1532 else
1533 fn.SetExt( FILEEXT::ReportFileExtension );
1534
1535 drcJob->m_outputFile = fn.GetFullName();
1536 }
1537
1538 EDA_UNITS units;
1539
1540 switch( drcJob->m_units )
1541 {
1542 case JOB_PCB_DRC::UNITS::INCHES: units = EDA_UNITS::INCHES; break;
1543 case JOB_PCB_DRC::UNITS::MILS: units = EDA_UNITS::MILS; break;
1544 case JOB_PCB_DRC::UNITS::MILLIMETERS: units = EDA_UNITS::MILLIMETRES; break;
1545 default: units = EDA_UNITS::MILLIMETRES; break;
1546 }
1547
1548 std::shared_ptr<DRC_ENGINE> drcEngine = brd->GetDesignSettings().m_DRCEngine;
1549 std::unique_ptr<NETLIST> netlist = std::make_unique<NETLIST>();
1550
1551 drcEngine->SetDrawingSheet( getDrawingSheetProxyView( brd ) );
1552
1553 // BOARD_COMMIT uses TOOL_MANAGER to grab the board internally so we must give it one
1554 TOOL_MANAGER* toolManager = new TOOL_MANAGER;
1555 toolManager->SetEnvironment( brd, nullptr, nullptr, Kiface().KifaceSettings(), nullptr );
1556
1557 BOARD_COMMIT commit( toolManager );
1558
1559 m_reporter->Report( _( "Running DRC...\n" ), RPT_SEVERITY_INFO );
1560
1561 if( drcJob->m_parity )
1562 {
1563 typedef bool (*NETLIST_FN_PTR)( const wxString&, std::string& );
1564
1566 wxFileName schematicPath( drcJob->m_filename );
1567 NETLIST_FN_PTR netlister = (NETLIST_FN_PTR) eeschema->IfaceOrAddress( KIFACE_NETLIST_SCHEMATIC );
1568 std::string netlist_str;
1569
1570 schematicPath.SetExt( FILEEXT::KiCadSchematicFileExtension );
1571
1572 if( !schematicPath.Exists() )
1573 schematicPath.SetExt( FILEEXT::LegacySchematicFileExtension );
1574
1575 if( !schematicPath.Exists() )
1576 {
1577 m_reporter->Report( _( "Failed to find schematic for parity tests.\n" ),
1579 }
1580 else
1581 {
1582 (*netlister)( schematicPath.GetFullPath(), netlist_str );
1583
1584 try
1585 {
1586 auto lineReader = new STRING_LINE_READER( netlist_str, _( "Eeschema netlist" ) );
1587 KICAD_NETLIST_READER netlistReader( lineReader, netlist.get() );
1588 netlistReader.LoadNetlist();
1589 }
1590 catch( const IO_ERROR& )
1591 {
1592 m_reporter->Report( _( "Failed to fetch schematic netlist for parity tests.\n" ),
1594 }
1595
1596 drcEngine->SetSchematicNetlist( netlist.get() );
1597 }
1598 }
1599
1600 drcEngine->SetProgressReporter( nullptr );
1601 drcEngine->SetViolationHandler(
1602 [&]( const std::shared_ptr<DRC_ITEM>& aItem, VECTOR2I aPos, int aLayer )
1603 {
1604 PCB_MARKER* marker = new PCB_MARKER( aItem, aPos, aLayer );
1605 commit.Add( marker );
1606 } );
1607
1608 brd->RecordDRCExclusions();
1609 brd->DeleteMARKERs( true, true );
1610 drcEngine->RunTests( units, drcJob->m_reportAllTrackErrors, drcJob->m_parity );
1611 drcEngine->ClearViolationHandler();
1612
1613 commit.Push( _( "DRC" ), SKIP_UNDO | SKIP_SET_DIRTY );
1614
1615 // Update the exclusion status on any excluded markers that still exist.
1616 brd->ResolveDRCExclusions( false );
1617
1618 std::shared_ptr<DRC_ITEMS_PROVIDER> markersProvider = std::make_shared<DRC_ITEMS_PROVIDER>(
1620
1621 std::shared_ptr<DRC_ITEMS_PROVIDER> ratsnestProvider =
1622 std::make_shared<DRC_ITEMS_PROVIDER>( brd, MARKER_BASE::MARKER_RATSNEST );
1623
1624 std::shared_ptr<DRC_ITEMS_PROVIDER> fpWarningsProvider =
1625 std::make_shared<DRC_ITEMS_PROVIDER>( brd, MARKER_BASE::MARKER_PARITY );
1626
1627 markersProvider->SetSeverities( drcJob->m_severity );
1628 ratsnestProvider->SetSeverities( drcJob->m_severity );
1629 fpWarningsProvider->SetSeverities( drcJob->m_severity );
1630
1631 m_reporter->Report( wxString::Format( _( "Found %d violations\n" ),
1632 markersProvider->GetCount() ),
1634 m_reporter->Report( wxString::Format( _( "Found %d unconnected items\n" ),
1635 ratsnestProvider->GetCount() ),
1637
1638 if( drcJob->m_parity )
1639 {
1640 m_reporter->Report( wxString::Format( _( "Found %d schematic parity issues\n" ),
1641 fpWarningsProvider->GetCount() ),
1643 }
1644
1645 DRC_REPORT reportWriter( brd, units, markersProvider, ratsnestProvider, fpWarningsProvider );
1646
1647 bool wroteReport = false;
1648
1650 wroteReport = reportWriter.WriteJsonReport( drcJob->m_outputFile );
1651 else
1652 wroteReport = reportWriter.WriteTextReport( drcJob->m_outputFile );
1653
1654 if( !wroteReport )
1655 {
1656 m_reporter->Report( wxString::Format( _( "Unable to save DRC report to %s\n" ),
1657 drcJob->m_outputFile ),
1660 }
1661
1662 m_reporter->Report( wxString::Format( _( "Saved DRC Report to %s\n" ),
1663 drcJob->m_outputFile ),
1665
1666 if( drcJob->m_exitCodeViolations )
1667 {
1668 if( markersProvider->GetCount() > 0 || ratsnestProvider->GetCount() > 0
1669 || fpWarningsProvider->GetCount() > 0 )
1670 {
1672 }
1673 }
1674
1676}
1677
1678
1680{
1681 JOB_EXPORT_PCB_IPC2581* job = dynamic_cast<JOB_EXPORT_PCB_IPC2581*>( aJob );
1682
1683 if( job == nullptr )
1685
1686 BOARD* brd = getBoard( job->m_filename );
1687
1688 if( !brd )
1690
1691 if( job->OutputPathFullSpecified() )
1692 {
1693 wxFileName fn = brd->GetFileName();
1694 fn.SetName( fn.GetName() );
1695 fn.SetExt( FILEEXT::Ipc2581FileExtension );
1696
1697 job->SetOutputPath( fn.GetName() );
1698 }
1699
1700 std::map<std::string, UTF8> props;
1701 props["units"] = job->m_units == JOB_EXPORT_PCB_IPC2581::IPC2581_UNITS::MILLIMETERS ? "mm"
1702 : "inch";
1703 props["sigfig"] = wxString::Format( "%d", job->m_precision );
1704 props["version"] = job->m_version == JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION::C ? "C" : "B";
1705 props["OEMRef"] = job->m_colInternalId;
1706 props["mpn"] = job->m_colMfgPn;
1707 props["mfg"] = job->m_colMfg;
1708 props["dist"] = job->m_colDist;
1709 props["distpn"] = job->m_colDistPn;
1710
1711 wxString tempFile = wxFileName::CreateTempFileName( wxS( "pcbnew_ipc" ) );
1712 try
1713 {
1715 pi->SetProgressReporter( m_progressReporter );
1716 pi->SaveBoard( tempFile, brd, &props );
1717 }
1718 catch( const IO_ERROR& ioe )
1719 {
1720 m_reporter->Report( wxString::Format( _( "Error generating IPC2581 file '%s'.\n%s" ),
1721 job->m_filename, ioe.What() ),
1723
1724 wxRemoveFile( tempFile );
1725
1727 }
1728
1729 if( job->m_compress )
1730 {
1731 wxFileName tempfn = job->GetFullOutputPath();
1732 tempfn.SetExt( FILEEXT::Ipc2581FileExtension );
1733 wxFileName zipfn = tempFile;
1734 zipfn.SetExt( "zip" );
1735
1736 wxFFileOutputStream fnout( zipfn.GetFullPath() );
1737 wxZipOutputStream zip( fnout );
1738 wxFFileInputStream fnin( tempFile );
1739
1740 zip.PutNextEntry( tempfn.GetFullName() );
1741 fnin.Read( zip );
1742 zip.Close();
1743 fnout.Close();
1744
1745 wxRemoveFile( tempFile );
1746 tempFile = zipfn.GetFullPath();
1747 }
1748
1749 // If save succeeded, replace the original with what we just wrote
1750 if( !wxRenameFile( tempFile, job->GetFullOutputPath() ) )
1751 {
1752 m_reporter->Report( wxString::Format( _( "Error generating IPC2581 file '%s'.\n"
1753 "Failed to rename temporary file '%s." )
1754 + wxS( "\n" ),
1755 job->GetFullOutputPath(), tempFile ),
1757 }
1758
1760}
1761
1762
1764{
1766 &aBrd->GetPageSettings(),
1767 aBrd->GetProject(),
1768 &aBrd->GetTitleBlock(),
1769 &aBrd->GetProperties() );
1770
1771 drawingSheet->SetSheetName( std::string() );
1772 drawingSheet->SetSheetPath( std::string() );
1773 drawingSheet->SetIsFirstPage( true );
1774
1775 drawingSheet->SetFileName( TO_UTF8( aBrd->GetFileName() ) );
1776
1777 return drawingSheet;
1778}
1779
1780
1781void PCBNEW_JOBS_HANDLER::loadOverrideDrawingSheet( BOARD* aBrd, const wxString& aSheetPath )
1782{
1783 // dont bother attempting to load a empty path, if there was one
1784 if( aSheetPath.IsEmpty() )
1785 return;
1786
1787 auto loadSheet =
1788 [&]( const wxString& path ) -> bool
1789 {
1792 resolver.SetProject( aBrd->GetProject() );
1794
1796 aBrd->GetProject()->GetProjectPath(),
1797 aBrd->GetEmbeddedFiles() );
1798 wxString msg;
1799
1800 if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename, &msg ) )
1801 {
1802 m_reporter->Report( wxString::Format( _( "Error loading drawing sheet '%s'." ),
1803 path )
1804 + wxS( "\n" ) + msg + wxS( "\n" ),
1806 return false;
1807 }
1808
1809 return true;
1810 };
1811
1812 if( loadSheet( aSheetPath ) )
1813 return;
1814
1815 // failed loading custom path, revert back to default
1816 loadSheet( aBrd->GetProject()->GetProjectFile().m_BoardDrawingSheetFile );
1817}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
Definition: board_adapter.h:66
PROJECTION_TYPE
Definition: camera.h:40
static wxString m_DrawingSheetFileName
the name of the drawing sheet file, or empty to use the default drawing sheet
Definition: base_screen.h:85
Helper class to handle information needed to display 3D board.
Definition: board_adapter.h:73
double BiuTo3dUnits() const noexcept
Board integer units To 3D units.
bool m_IsPreviewer
true if we're in a 3D preview panel, false for the standard 3D viewer
void SetBoard(BOARD *aBoard) noexcept
Set current board to be rendered.
EDA_3D_VIEWER_SETTINGS * m_Cfg
std::map< int, COLOR4D > m_ColorOverrides
allows to override color scheme colors
void Set3dCacheManager(S3D_CACHE *aCacheMgr) noexcept
Update the cache manager pointer.
Definition: board_adapter.h:84
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
const VECTOR2I & GetAuxOrigin()
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:290
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:773
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition: board.cpp:2544
const PAGE_INFO & GetPageSettings() const
Definition: board.h:689
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: board.cpp:327
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:695
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1668
const std::map< wxString, wxString > & GetProperties() const
Definition: board.h:362
const wxString & GetFileName() const
Definition: board.h:327
std::vector< PCB_MARKER * > ResolveDRCExclusions(bool aCreateMarkers)
Rebuild DRC markers from the serialized data in BOARD_DESIGN_SETTINGS.
Definition: board.cpp:344
const PCB_PLOT_PARAMS & GetPlotOptions() const
Definition: board.h:692
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:577
PROJECT * GetProject() const
Definition: board.h:491
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:890
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition: board.cpp:2040
void DeleteMARKERs()
Delete all MARKERS from the board.
Definition: board.cpp:1355
constexpr const Vec GetCenter() const
Definition: box2.h:230
void SetProjection(PROJECTION_TYPE aProjection)
Definition: camera.h:206
void RotateY_T1(float aAngleInRadians)
Definition: camera.cpp:685
bool Zoom_T1(float aFactor)
Definition: camera.cpp:628
bool SetCurWindowSize(const wxSize &aSize)
Update the windows size of the camera.
Definition: camera.cpp:570
bool ViewCommand_T1(VIEW3D_TYPE aRequestedView)
Definition: camera.cpp:110
void RotateX_T1(float aAngleInRadians)
Definition: camera.cpp:679
void SetLookAtPos_T1(const SFVEC3F &aLookAtPos)
Definition: camera.h:162
const SFVEC3F & GetLookAtPos_T1() const
Definition: camera.h:167
void RotateZ_T1(float aAngleInRadians)
Definition: camera.cpp:691
bool ParametersChanged()
Definition: camera.cpp:729
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been added.
Definition: commit.h:80
The dialog to create footprint position files and choose options (one or 2 files, units and force all...
A dialog to set the plot options and create plot files in various formats.
Definition: dialog_plot.h:41
bool WriteJsonReport(const wxString &aFullFileName)
Definition: drc_report.cpp:114
bool WriteTextReport(const wxString &aFullFileName)
Definition: drc_report.cpp:47
Helper to handle drill precision format in excellon files.
bool LoadDrawingSheet(const wxString &aFullFileName, wxString *aMsg, bool aAppend=false)
Populates the list with a custom layout or the default layout if no custom layout is available.
static DS_DATA_MODEL & GetTheInstance()
static function: returns the instance of DS_DATA_MODEL used in the application
void SetSheetPath(const std::string &aSheetPath)
Set the sheet path displayed in the title block.
void SetSheetName(const std::string &aSheetName)
Set the sheet name displayed in the title block.
void SetIsFirstPage(bool aIsFirstPage)
Change if this is first page.
void SetFileName(const std::string &aFileName)
Set the file name displayed in the title block.
virtual bool EndPlot() override
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:127
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:104
Create Excellon drill, drill map, and drill report files.
void SetFormat(bool aMetric, ZEROS_FMT aZerosFmt=DECIMAL_FORMAT, int aLeftDigits=0, int aRightDigits=0)
Initialize internal parameters to match the given format.
bool CreateDrillandMapFilesSet(const wxString &aPlotDirectory, bool aGenDrill, bool aGenMap, REPORTER *aReporter=nullptr)
Create the full set of Excellon drill file for the board.
void SetOptions(bool aMirror, bool aMinimalHeader, const VECTOR2I &aOffset, bool aMerge_PTH_NPTH)
Initialize internal parameters to match drill options.
void SetRouteModeForOvalHoles(bool aUseRouteModeForOvalHoles)
wxString m_outputFile
Definition: exporter_step.h:53
Wrapper to expose an API for writing VRML files, without exposing all the many structures used in the...
Definition: export_vrml.h:33
bool ExportVRML_File(PROJECT *aProject, wxString *aMessages, const wxString &aFullFileName, double aMMtoWRMLunit, bool aIncludeUnspecified, bool aIncludeDNP, bool aExport3DFiles, bool aUseRelativePaths, const wxString &a3D_Subdir, double aXRef, double aYRef)
Exports the board and its footprint shapes 3D (vrml files only) as a vrml file.
static bool Plot(BOARD *aBoard, const PCB_PLOT_SVG_OPTIONS &aSvgPlotOptions)
Definition: export_svg.cpp:29
Provide an extensible class to resolve 3D model paths.
bool SetProject(PROJECT *aProject, bool *flgChanged=nullptr)
Set the current KiCad project directory as the first entry in the model path list.
void SetProgramBase(PGM_BASE *aBase)
Set a pointer to the application's PGM_BASE instance used to extract the local env vars.
wxString ResolvePath(const wxString &aFileName, const wxString &aWorkingPath, const EMBEDDED_FILES *aFiles)
Determines the full path of the given file name.
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2334
void SetLink(const KIID &aLink)
Definition: footprint.h:852
void SetOrientation(const EDA_ANGLE &aNewAngle)
Definition: footprint.cpp:2404
EDA_ITEM * Clone() const override
Invoke a function on all children.
Definition: footprint.cpp:2025
std::deque< PAD * > & Pads()
Definition: footprint.h:205
const LIB_ID & GetFPID() const
Definition: footprint.h:247
FP_CACHE_FOOTPRINT_MAP & GetFootprints()
void Save(FOOTPRINT *aFootprint=nullptr)
Save the footprint cache or a single footprint from it to disk.
void SetPath(const wxString &aPath)
void UseIndividualShapes(bool aUnique)
Make pad shapes unique.
void UsePinNamesUnique(bool aUnique)
Make pin names unique.
void StoreOriginCoordsInFile(bool aStore)
Store coord origin in genCAD file.
void FlipBottomPads(bool aFlip)
Flip pad shapes on the bottom side.
void SetPlotOffet(VECTOR2I aOffset)
Set the coordinates offet when exporting items.
bool WriteFile(const wxString &aFullFileName)
Export a genCAD file.
void SetMapFileFormat(PLOT_FORMAT aMapFmt)
Initialize the format for the drill map file.
GERBER_JOBFILE_WRITER is a class used to create Gerber job file a Gerber job file stores info to make...
bool CreateJobFile(const wxString &aFullFilename)
Creates a Gerber job file.
void AddGbrFile(PCB_LAYER_ID aLayer, wxString &aFilename)
add a gerber file name and type in job file list
virtual bool EndPlot() override
Used to create Gerber drill files.
bool CreateDrillandMapFilesSet(const wxString &aPlotDirectory, bool aGenDrill, bool aGenMap, REPORTER *aReporter=nullptr)
Create the full set of Excellon drill file for the board filenames are computed from the board name,...
void SetOptions(const VECTOR2I &aOffset)
Initialize internal parameters to match drill options.
void SetFormat(int aRightDigits=6)
Initialize internal parameters to match the given format.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
void Register(const std::string &aJobTypeName, std::function< int(JOB *job)> aHandler, std::function< bool(JOB *job, wxWindow *aParent)> aConfigHandler)
PROGRESS_REPORTER * m_progressReporter
REPORTER * m_reporter
JOB_EXPORT_PCB_3D::FORMAT m_format
EXPORTER_STEP_PARAMS m_3dparams
Despite the name; also used for other formats.
bool m_mirror
Common Options.
wxString m_libraryPath
wxString m_outputLibraryPath
OUTPUT_FORMAT m_format
Definition: job_pcb_drc.h:58
UNITS m_units
Definition: job_pcb_drc.h:48
bool m_parity
Definition: job_pcb_drc.h:61
wxString m_filename
Definition: job_pcb_drc.h:36
int m_severity
Definition: job_pcb_drc.h:50
bool m_reportAllTrackErrors
Definition: job_pcb_drc.h:39
wxString m_outputFile
Definition: job_pcb_drc.h:37
bool m_exitCodeViolations
Definition: job_pcb_drc.h:60
BG_STYLE m_bgStyle
VECTOR3D m_rotation
wxString m_filename
VECTOR3D m_pivot
std::string m_colorPreset
wxString m_outputFile
An simple container class that lets us dispatch output jobs to kifaces.
Definition: job.h:79
void AddOutput(wxString aOutputPath)
Definition: job.h:112
wxString GetFullOutputPath() const
Definition: job.cpp:88
bool OutputPathFullSpecified() const
Definition: job.cpp:136
bool IsCli() const
Definition: job.h:86
void SetOutputPath(const wxString &aPath)
Definition: job.cpp:130
const std::map< wxString, wxString > & GetVarOverrides() const
Definition: job.h:88
wxString GetOutputPath() const
Definition: job.h:120
Read the new s-expression based KiCad netlist format.
virtual void LoadNetlist() override
Load the contents of the netlist file into aNetlist.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition: kiway.h:284
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:406
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition: kiway.cpp:202
@ FACE_SCH
eeschema DSO
Definition: kiway.h:291
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
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:36
LSEQ UIOrder() const
Returns the copper, technical and user layers in the order shown in layer widget.
Definition: lset.cpp:799
LSEQ SeqStackupForPlotting() const
Return the sequence that is typical for a bottom-to-top stack-up.
Definition: lset.cpp:500
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:687
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
@ MARKER_DRAWING_SHEET
Definition: marker_base.h:56
Definition: pad.h:54
void populateGerberPlotOptionsFromJob(PCB_PLOT_PARAMS &aPlotOpts, JOB_EXPORT_PCB_GERBER *aJob)
int JobExportFpUpgrade(JOB *aJob)
int JobExportGerber(JOB *aJob)
DS_PROXY_VIEW_ITEM * getDrawingSheetProxyView(BOARD *aBrd)
void loadOverrideDrawingSheet(BOARD *brd, const wxString &aSheetPath)
PCBNEW_JOBS_HANDLER(KIWAY *aKiway)
int JobExportGerbers(JOB *aJob)
int JobExportGencad(JOB *aJob)
BOARD * getBoard(const wxString &aPath=wxEmptyString)
int JobExportRender(JOB *aJob)
int doFpExportSvg(JOB_FP_EXPORT_SVG *aSvgJob, const FOOTPRINT *aFootprint)
The main frame for Pcbnew.
A #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
static PCB_IO * PluginFind(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
Definition: pcb_io_mgr.cpp:69
PCB_FILE_T
The set of file types that the PCB_IO_MGR knows about, and for which there has been a plugin written,...
Definition: pcb_io_mgr.h:56
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition: pcb_io_mgr.h:58
static bool ConvertLibrary(std::map< std::string, UTF8 > *aOldFileProps, const wxString &aOldFilePath, const wxString &aNewFilePath, REPORTER *aReporter)
Convert a schematic symbol library to the latest KiCad format.
Definition: pcb_io_mgr.cpp:191
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a footprint library's libPath.
Definition: pcb_io_mgr.cpp:136
Parameters and options when plotting/printing a board.
void SetDrillMarksType(DRILL_MARKS aVal)
void SetLayerSelection(LSET aSelection)
void SetPlotReference(bool aFlag)
void SetSketchPadsOnFabLayers(bool aFlag)
void SetUseGerberX2format(bool aUse)
void SetDXFPlotPolygonMode(bool aFlag)
void SetPlotFrameRef(bool aFlag)
void SetSketchDNPFPsOnFabLayers(bool aFlag)
void SetPlotPadNumbers(bool aFlag)
LSET GetLayerSelection() const
LSET GetPlotOnAllLayersSelection() const
void SetDisableGerberMacros(bool aDisable)
void SetMirror(bool aFlag)
void SetBlackAndWhite(bool blackAndWhite)
void SetGerberPrecision(int aPrecision)
void SetSubtractMaskFromSilk(bool aSubtract)
void SetHideDNPFPsOnFabLayers(bool aFlag)
void SetPlotValue(bool aFlag)
void SetUseGerberProtelExtensions(bool aUse)
void SetDXFPlotUnits(DXF_UNITS aUnit)
void SetColorSettings(COLOR_SETTINGS *aSettings)
void SetIncludeGerberNetlistInfo(bool aUse)
void SetNegative(bool aFlag)
void SetUseAuxOrigin(bool aAux)
bool GetUseGerberProtelExtensions() const
void SetCrossoutDNPFPsOnFabLayers(bool aFlag)
void SetFormat(PLOT_FORMAT aFormat)
virtual bool EndPlot() override
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:142
Used to create Gerber drill files.
int CreatePlaceFile(const wxString &aFullFilename, PCB_LAYER_ID aLayer, bool aIncludeBrdEdges)
Create an pnp gerber file.
The ASCII format of the kicad place file is:
std::string GenPositionData()
build a string filled with the position data
wxString m_BoardDrawingSheetFile
PcbNew params.
Definition: project_file.h:159
static S3D_CACHE * Get3DCacheManager(PROJECT *aProject, bool updateProjDir=false)
Return a pointer to an instance of the 3D cache manager.
Definition: project_pcb.cpp:77
Container for project specific data.
Definition: project.h:64
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:135
virtual void ApplyTextVars(const std::map< wxString, wxString > &aVarsMap)
Applies the given var map, it will create or update existing vars.
Definition: project.cpp:90
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:200
bool Redraw(bool aIsMoving, REPORTER *aStatusReporter, REPORTER *aWarningReporter) override
Redraw the view.
void SetCurWindowSize(const wxSize &aSize) override
Before each render, the canvas will tell the render what is the size of its windows,...
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
T * GetAppSettings()
Returns a handle to the a given settings by type If the settings have already been loaded,...
COLOR_SETTINGS * GetColorSettings(const wxString &aName="user")
Retrieves a color settings object that applications can read colors from.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition: richio.h:253
Master controller class:
Definition: tool_manager.h:62
void SetEnvironment(EDA_ITEM *aModel, KIGFX::VIEW *aView, KIGFX::VIEW_CONTROLS *aViewControls, APP_SETTINGS_BASE *aSettings, TOOLS_HOLDER *aFrame)
Set the work environment (model, view, view controls and the parent window).
void Pan_T1(const SFVEC3F &aDeltaOffsetInc) override
Definition: track_ball.cpp:125
void SetT0_and_T1_current_T() override
This will set T0 and T1 with the current values.
Definition: track_ball.cpp:138
void Interpolate(float t) override
It will update the matrix to interpolate between T0 and T1 values.
Definition: track_ball.cpp:152
wxString wx_str() const
Definition: utf8.cpp:45
T y
Definition: vector3.h:63
T z
Definition: vector3.h:64
T x
Definition: vector3.h:62
wxString GetDefaultPlotExtension(PLOT_FORMAT aFormat)
Returns the default plot extension for a format.
static DRILL_PRECISION precisionListForInches(2, 4)
static DRILL_PRECISION precisionListForMetric(3, 3)
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:401
#define IS_NEW
New item, just created.
EDA_UNITS
Definition: eda_units.h:46
static FILENAME_RESOLVER * resolver
Definition: export_idf.cpp:53
@ FRAME_PCB_EDITOR
Definition: frame_type.h:42
Classes used in drill files, map files and report files generation.
Classes used in drill files, map files and report files generation.
Classes used to generate a Gerber job file in JSON.
Classes used in place file generation.
static const std::string LegacySchematicFileExtension
static const std::string BrepFileExtension
static const std::string GerberJobFileExtension
static const std::string GerberFileExtension
static const std::string XaoFileExtension
static const std::string ReportFileExtension
static const std::string GltfBinaryFileExtension
static const std::string FootprintPlaceFileExtension
static const std::string JsonFileExtension
static const std::string KiCadSchematicFileExtension
static const std::string CsvFileExtension
static const std::string Ipc2581FileExtension
static const std::string StepFileExtension
static const std::string SVGFileExtension
static const std::string VrmlFileExtension
static const std::string KiCadPcbFileExtension
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition: io_mgr.h:33
PROJECT & Prj()
Definition: kicad.cpp:595
@ KIFACE_NETLIST_SCHEMATIC
Definition: kiface_ids.h:56
KIID niluuid(0)
@ LAYER_3D_BACKGROUND_TOP
Definition: layer_ids.h:453
@ LAYER_3D_BACKGROUND_BOTTOM
Definition: layer_ids.h:452
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Cu
Definition: layer_ids.h:65
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ F_Cu
Definition: layer_ids.h:64
This file contains miscellaneous commonly used macros and functions.
static const int OK
Definition: exit_codes.h:30
static const int ERR_RC_VIOLATIONS
Definition: exit_codes.h:36
static const int ERR_INVALID_INPUT_FILE
Definition: exit_codes.h:33
static const int SUCCESS
Definition: exit_codes.h:29
static const int ERR_INVALID_OUTPUT_CONFLICT
Rules check violation count was greater than 0.
Definition: exit_codes.h:34
static const int ERR_UNKNOWN
Definition: exit_codes.h:32
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
boost::ptr_map< wxString, FP_CACHE_ITEM > FP_CACHE_FOOTPRINT_MAP
#define CTL_FOR_LIBRARY
Format output for a footprint library instead of clipboard or BOARD.
static DRILL_PRECISION precisionListForInches(2, 4)
static DRILL_PRECISION precisionListForMetric(3, 3)
FOOTPRINT * try_load_footprint(const wxFileName &aFileName, PCB_IO_MGR::PCB_FILE_T aFileType, const wxString &aName)
SETTINGS_MANAGER * GetSettingsManager()
BOARD * CreateEmptyBoard()
Construct a default BOARD with a temporary (no filename) project.
BOARD * LoadBoard(const wxString &aFileName, bool aSetActive, PROJECT *aProject)
Loads a board from file This function identifies the file type by extension and determines the correc...
const wxString GetGerberProtelExtension(int aLayer)
Definition: pcbplot.cpp:43
void BuildPlotFileName(wxFileName *aFilename, const wxString &aOutputDir, const wxString &aSuffix, const wxString &aExtension)
Complete a plot filename.
Definition: pcbplot.cpp:373
void PlotBoardLayers(BOARD *aBoard, PLOTTER *aPlotter, const LSEQ &aLayerSequence, const PCB_PLOT_PARAMS &aPlotOptions)
Plot a sequence of board layer IDs.
void PlotInteractiveLayer(BOARD *aBoard, PLOTTER *aPlotter, const PCB_PLOT_PARAMS &aPlotOpt)
Plot interactive items (hypertext links, properties, etc.).
PLOTTER * StartPlotBoard(BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aLayer, const wxString &aLayerName, const wxString &aFullFileName, const wxString &aSheetName, const wxString &aSheetPath)
Open a new plotfile using the options (and especially the format) specified in the options and prepar...
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1060
see class PGM_BASE
PLOT_FORMAT
The set of supported output plot formats.
Definition: plotter.h:65
Plotting engines similar to ps (PostScript, Gerber, svg)
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
#define SKIP_SET_DIRTY
Definition: sch_commit.h:43
#define SKIP_UNDO
Definition: sch_commit.h:41
const int scale
MODEL3D_FORMAT_TYPE fileType(const char *aFileName)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:391
constexpr double IUTomm(int iu) const
Definition: base_units.h:86
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
Implement a participant in the KIWAY alchemy.
Definition: kiway.h:151
bool m_sketchPadsOnFabLayers
Definition: export_svg.h:37
bool m_sketchDNPFPsOnFabLayers
Definition: export_svg.h:39
wxString m_colorTheme
Definition: export_svg.h:27
wxString m_outputFile
Definition: export_svg.h:26
bool m_crossoutDNPFPsOnFabLayers
Definition: export_svg.h:40
bool m_hideDNPFPsOnFabLayers
Definition: export_svg.h:38
Declaration for a track ball camera.
double DEG2RAD(double deg)
Definition: trigo.h:166
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691
Definition of file extensions used in Kicad.
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44