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 The 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>
42#include <jobs/job_pcb_render.h>
43#include <jobs/job_pcb_drc.h>
44#include <lset.h>
45#include <cli/exit_codes.h>
51#include <tool/tool_manager.h>
52#include <tools/drc_tool.h>
53#include <filename_resolver.h>
58#include <kiface_base.h>
59#include <macros.h>
60#include <pad.h>
61#include <pcb_marker.h>
65#include <kiface_ids.h>
68#include <pcbnew_settings.h>
69#include <pcbplot.h>
70#include <pcb_plotter.h>
71#include <pgm_base.h>
74#include <project_pcb.h>
76#include <reporter.h>
78#include <export_vrml.h>
79#include <wx/wfstream.h>
80#include <wx/zipstrm.h>
87#include <dialogs/dialog_plot.h>
90#include <paths.h>
91
93#include <locale_io.h>
94
95
96#ifdef _WIN32
97#ifdef TRANSPARENT
98#undef TRANSPARENT
99#endif
100#endif
101
102
104 JOB_DISPATCHER( aKiway ),
105 m_cliBoard( nullptr )
106{
107 Register( "3d", std::bind( &PCBNEW_JOBS_HANDLER::JobExportStep, this, std::placeholders::_1 ),
108 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
109 {
110 JOB_EXPORT_PCB_3D* svgJob = dynamic_cast<JOB_EXPORT_PCB_3D*>( job );
111
112 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
113 aKiway->Player( FRAME_PCB_EDITOR, false ) );
114
115 wxCHECK( svgJob && editFrame, false );
116
117 DIALOG_EXPORT_STEP dlg( editFrame, aParent, "", svgJob );
118 return dlg.ShowModal() == wxID_OK;
119 } );
120 Register( "render",
121 std::bind( &PCBNEW_JOBS_HANDLER::JobExportRender, this, std::placeholders::_1 ),
122 []( JOB* job, wxWindow* aParent ) -> bool
123 {
124 DIALOG_RENDER_JOB dlg( aParent, dynamic_cast<JOB_PCB_RENDER*>( job ) );
125 return dlg.ShowModal() == wxID_OK;
126 } );
127 Register( "svg", std::bind( &PCBNEW_JOBS_HANDLER::JobExportSvg, this, std::placeholders::_1 ),
128 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
129 {
130 JOB_EXPORT_PCB_SVG* svgJob = dynamic_cast<JOB_EXPORT_PCB_SVG*>( job );
131
132 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
133 aKiway->Player( FRAME_PCB_EDITOR, false ) );
134
135 wxCHECK( svgJob && editFrame, false );
136
137 DIALOG_PLOT dlg( editFrame, aParent, svgJob );
138 return dlg.ShowModal() == wxID_OK;
139 } );
140 Register( "gencad",
141 std::bind( &PCBNEW_JOBS_HANDLER::JobExportGencad, this, std::placeholders::_1 ),
142 []( JOB* job, wxWindow* aParent ) -> bool
143 {
144 return true;
145 } );
146 Register( "dxf", std::bind( &PCBNEW_JOBS_HANDLER::JobExportDxf, this, std::placeholders::_1 ),
147 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
148 {
149 JOB_EXPORT_PCB_DXF* dxfJob = dynamic_cast<JOB_EXPORT_PCB_DXF*>( job );
150
151 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
152 aKiway->Player( FRAME_PCB_EDITOR, false ) );
153
154 wxCHECK( dxfJob && editFrame, false );
155
156 DIALOG_PLOT dlg( editFrame, aParent, dxfJob );
157 return dlg.ShowModal() == wxID_OK;
158 } );
159 Register( "pdf", std::bind( &PCBNEW_JOBS_HANDLER::JobExportPdf, this, std::placeholders::_1 ),
160 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
161 {
162 JOB_EXPORT_PCB_PDF* pdfJob = dynamic_cast<JOB_EXPORT_PCB_PDF*>( job );
163
164 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
165 aKiway->Player( FRAME_PCB_EDITOR, false ) );
166
167 wxCHECK( pdfJob && editFrame, false );
168
169 DIALOG_PLOT dlg( editFrame, aParent, pdfJob );
170 return dlg.ShowModal() == wxID_OK;
171 } );
172 Register( "gerber",
173 std::bind( &PCBNEW_JOBS_HANDLER::JobExportGerber, this, std::placeholders::_1 ),
174 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
175 {
176 JOB_EXPORT_PCB_GERBER* gJob = dynamic_cast<JOB_EXPORT_PCB_GERBER*>( job );
177
178 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
179 aKiway->Player( FRAME_PCB_EDITOR, false ) );
180
181 wxCHECK( gJob && editFrame, false );
182
183 DIALOG_PLOT dlg( editFrame, aParent, gJob );
184 return dlg.ShowModal() == wxID_OK;
185 } );
186 Register( "gerbers",
187 std::bind( &PCBNEW_JOBS_HANDLER::JobExportGerbers, this, std::placeholders::_1 ),
188 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
189 {
190 JOB_EXPORT_PCB_GERBERS* gJob = dynamic_cast<JOB_EXPORT_PCB_GERBERS*>( job );
191
192 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
193 aKiway->Player( FRAME_PCB_EDITOR, false ) );
194
195 wxCHECK( gJob && editFrame, false );
196
197 DIALOG_PLOT dlg( editFrame, aParent, gJob );
198 return dlg.ShowModal() == wxID_OK;
199 } );
200 Register( "drill",
201 std::bind( &PCBNEW_JOBS_HANDLER::JobExportDrill, this, std::placeholders::_1 ),
202 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
203 {
204 JOB_EXPORT_PCB_DRILL* drillJob = dynamic_cast<JOB_EXPORT_PCB_DRILL*>( job );
205
206 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
207 aKiway->Player( FRAME_PCB_EDITOR, false ) );
208
209 wxCHECK( drillJob && editFrame, false );
210
211 DIALOG_GENDRILL dlg( editFrame, drillJob, aParent );
212 return dlg.ShowModal() == wxID_OK;
213 } );
214 Register( "pos", std::bind( &PCBNEW_JOBS_HANDLER::JobExportPos, this, std::placeholders::_1 ),
215 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
216 {
217 JOB_EXPORT_PCB_POS* posJob = dynamic_cast<JOB_EXPORT_PCB_POS*>( job );
218
219 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
220 aKiway->Player( FRAME_PCB_EDITOR, false ) );
221
222 wxCHECK( posJob && editFrame, false );
223
224 DIALOG_GEN_FOOTPRINT_POSITION dlg( posJob, editFrame, aParent );
225 return dlg.ShowModal() == wxID_OK;
226 } );
227 Register( "fpupgrade",
228 std::bind( &PCBNEW_JOBS_HANDLER::JobExportFpUpgrade, this, std::placeholders::_1 ),
229 []( JOB* job, wxWindow* aParent ) -> bool
230 {
231 return true;
232 } );
233 Register( "fpsvg",
234 std::bind( &PCBNEW_JOBS_HANDLER::JobExportFpSvg, this, std::placeholders::_1 ),
235 []( JOB* job, wxWindow* aParent ) -> bool
236 {
237 return true;
238 } );
239 Register( "drc", std::bind( &PCBNEW_JOBS_HANDLER::JobExportDrc, this, std::placeholders::_1 ),
240 []( JOB* job, wxWindow* aParent ) -> bool
241 {
242 DIALOG_DRC_JOB_CONFIG dlg( aParent, dynamic_cast<JOB_PCB_DRC*>( job ) );
243
244 return dlg.ShowModal() == wxID_OK;
245 } );
246 Register( "ipc2581",
247 std::bind( &PCBNEW_JOBS_HANDLER::JobExportIpc2581, this, std::placeholders::_1 ),
248 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
249 {
250 JOB_EXPORT_PCB_IPC2581* ipcJob = dynamic_cast<JOB_EXPORT_PCB_IPC2581*>( job );
251
252 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
253 aKiway->Player( FRAME_PCB_EDITOR, false ) );
254
255 wxCHECK( ipcJob && editFrame, false );
256
257 DIALOG_EXPORT_2581 dlg( ipcJob, editFrame, aParent );
258 return dlg.ShowModal() == wxID_OK;
259 } );
260 Register( "odb",
261 std::bind( &PCBNEW_JOBS_HANDLER::JobExportOdb, this, std::placeholders::_1 ),
262 [aKiway]( JOB* job, wxWindow* aParent ) -> bool
263 {
264 JOB_EXPORT_PCB_ODB* odbJob = dynamic_cast<JOB_EXPORT_PCB_ODB*>( job );
265
266 PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
267 aKiway->Player( FRAME_PCB_EDITOR, false ) );
268
269 wxCHECK( odbJob && editFrame, false );
270
271 DIALOG_EXPORT_ODBPP dlg( odbJob, editFrame, aParent );
272 return dlg.ShowModal() == wxID_OK;
273 } );
274}
275
276
277BOARD* PCBNEW_JOBS_HANDLER::getBoard( const wxString& aPath )
278{
279 BOARD* brd = nullptr;
280
281 if( !Pgm().IsGUI() && Pgm().GetSettingsManager().IsProjectOpen() )
282 {
283 wxString pcbPath = aPath;
284
285 if( pcbPath.IsEmpty() )
286 {
287 wxFileName path = Pgm().GetSettingsManager().Prj().GetProjectFullName();
289 path.MakeAbsolute();
290 pcbPath = path.GetFullPath();
291 }
292
293 if( !m_cliBoard )
294 m_cliBoard = LoadBoard( pcbPath, true );
295
296 brd = m_cliBoard;
297 }
298 else if( Pgm().IsGUI() && Pgm().GetSettingsManager().IsProjectOpen() )
299 {
301
302 if( editFrame )
303 brd = editFrame->GetBoard();
304 }
305 else
306 {
307 brd = LoadBoard( aPath, true );
308 }
309
310 if( !brd )
311 m_reporter->Report( _( "Failed to load board\n" ), RPT_SEVERITY_ERROR );
312
313 return brd;
314}
315
316
318{
319 JOB_EXPORT_PCB_3D* aStepJob = dynamic_cast<JOB_EXPORT_PCB_3D*>( aJob );
320
321 if( aStepJob == nullptr )
323
324 BOARD* brd = getBoard( aStepJob->m_filename );
325
326 if( !brd )
328
329 aJob->SetTitleBlock( brd->GetTitleBlock() );
330 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
332
333 if( aStepJob->GetConfiguredOutputPath().IsEmpty() )
334 {
335 wxFileName fn = brd->GetFileName();
336 fn.SetName( fn.GetName() );
337
338 switch( aStepJob->m_format )
339 {
341 break;
343 break;
345 break;
347 break;
349 break;
351 break;
353 break;
354 default:
355 m_reporter->Report( _( "Unknown export format" ), RPT_SEVERITY_ERROR );
356 return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here
357 }
358
359 aStepJob->SetWorkingOutputPath( fn.GetFullName() );
360 }
361
362 wxString outPath = aStepJob->GetFullOutputPath( brd->GetProject() );
363
364 if( !PATHS::EnsurePathExists( outPath, true ) )
365 {
366 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
368 }
369
371 {
372
373 double scale = 0.0;
374 switch ( aStepJob->m_vrmlUnits )
375 {
377 case JOB_EXPORT_PCB_3D::VRML_UNITS::METERS: scale = 0.001; break;
378 case JOB_EXPORT_PCB_3D::VRML_UNITS::TENTHS: scale = 10.0 / 25.4; break;
379 case JOB_EXPORT_PCB_3D::VRML_UNITS::INCHES: scale = 1.0 / 25.4; break;
380 }
381
382 EXPORTER_VRML vrmlExporter( brd );
383 wxString messages;
384
385 double originX = pcbIUScale.IUTomm( aStepJob->m_3dparams.m_Origin.x );
386 double originY = pcbIUScale.IUTomm( aStepJob->m_3dparams.m_Origin.y );
387
388 if( !aStepJob->m_hasUserOrigin )
389 {
390 BOX2I bbox = brd->ComputeBoundingBox( true );
391 originX = pcbIUScale.IUTomm( bbox.GetCenter().x );
392 originY = pcbIUScale.IUTomm( bbox.GetCenter().y );
393 }
394
395 bool success = vrmlExporter.ExportVRML_File(
396 brd->GetProject(), &messages, outPath, scale,
398 !aStepJob->m_vrmlModelDir.IsEmpty(), aStepJob->m_vrmlRelativePaths,
399 aStepJob->m_vrmlModelDir, originX, originY );
400
401 if ( success )
402 {
403 m_reporter->Report( wxString::Format( _( "Successfully exported VRML to %s" ),
404 outPath ),
406 }
407 else
408 {
409 m_reporter->Report( _( "Error exporting VRML" ), RPT_SEVERITY_ERROR );
411 }
412 }
413 else
414 {
415 EXPORTER_STEP_PARAMS params = aStepJob->m_3dparams;
416
417 switch( aStepJob->m_format )
418 {
421 break;
424 break;
427 break;
430 break;
433 break;
436 break;
437 default:
438 m_reporter->Report( _( "Unknown export format" ), RPT_SEVERITY_ERROR );
439 return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here
440 }
441
442 EXPORTER_STEP stepExporter( brd, params );
443 stepExporter.m_outputFile = aStepJob->GetFullOutputPath( brd->GetProject() );
444
445 if( !stepExporter.Export() )
447 }
448
449 return CLI::EXIT_CODES::OK;
450}
451
452
454{
455 JOB_PCB_RENDER* aRenderJob = dynamic_cast<JOB_PCB_RENDER*>( aJob );
456
457 if( aRenderJob == nullptr )
459
460 // Reject width and height being invalid
461 // Final bit of sanity because this can blow things up
462 if( aRenderJob->m_width <= 0 || aRenderJob->m_height <= 0 )
463 {
464 m_reporter->Report( _( "Invalid image dimensions" ), RPT_SEVERITY_ERROR );
466 }
467
468 BOARD* brd = getBoard( aRenderJob->m_filename );
469
470 if( !brd )
472
473 aJob->SetTitleBlock( brd->GetTitleBlock() );
474 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
476
477 if( aRenderJob->GetConfiguredOutputPath().IsEmpty() )
478 {
479 wxFileName fn = brd->GetFileName();
480
481 switch( aRenderJob->m_format )
482 {
485 default:
486 m_reporter->Report( _( "Unknown export format" ), RPT_SEVERITY_ERROR );
487 return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here
488 }
489
490 // set the name to board name + "side", its lazy but its hard to generate anything truely unique
491 // incase someone is doing this in a jobset with multiple jobs, they should be setting the output themselves
492 // or we do a hash based on all the options
493 fn.SetName( wxString::Format( "%s-%d", fn.GetName(), static_cast<int>( aRenderJob->m_side ) ) );
494
495 aRenderJob->SetWorkingOutputPath( fn.GetFullName() );
496 }
497
498 wxString outPath = aRenderJob->GetFullOutputPath( brd->GetProject() );
499
500 if( !PATHS::EnsurePathExists( outPath, true ) )
501 {
502 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
504 }
505
506 BOARD_ADAPTER boardAdapter;
507
508 boardAdapter.SetBoard( brd );
509 boardAdapter.m_IsBoardView = false;
510 boardAdapter.m_IsPreviewer = true; // Force display 3D models, regardless of 3D viewer options
511
514
515 if( aRenderJob->m_quality == JOB_PCB_RENDER::QUALITY::BASIC )
516 {
517 // Silkscreen is pixelated without antialiasing
519
520 cfg->m_Render.raytrace_backfloor = false;
522
524 cfg->m_Render.raytrace_reflections = false;
525 cfg->m_Render.raytrace_shadows = false;
526
527 // Better colors
529
530 // Tracks below soldermask are not visible without refractions
531 cfg->m_Render.raytrace_refractions = true;
533 }
534 else if( aRenderJob->m_quality == JOB_PCB_RENDER::QUALITY::HIGH )
535 {
537 cfg->m_Render.raytrace_backfloor = true;
540 cfg->m_Render.raytrace_reflections = true;
541 cfg->m_Render.raytrace_shadows = true;
542 cfg->m_Render.raytrace_refractions = true;
544 }
545
546 if( aRenderJob->m_floor )
547 {
548 cfg->m_Render.raytrace_backfloor = true;
549 cfg->m_Render.raytrace_shadows = true;
551 }
552
554 aRenderJob->m_lightTopIntensity.y,
555 aRenderJob->m_lightTopIntensity.z, 1.0);
556
558 aRenderJob->m_lightBottomIntensity.y,
559 aRenderJob->m_lightBottomIntensity.z, 1.0);
560
562 aRenderJob->m_lightCameraIntensity.y,
563 aRenderJob->m_lightCameraIntensity.z, 1.0 );
564
565 COLOR4D lightColor( aRenderJob->m_lightSideIntensity.x,
566 aRenderJob->m_lightSideIntensity.y,
567 aRenderJob->m_lightSideIntensity.z, 1.0 );
568
570 lightColor, lightColor, lightColor, lightColor,
571 lightColor, lightColor, lightColor, lightColor,
572 };
573
574 int sideElevation = aRenderJob->m_lightSideElevation;
575
577 sideElevation, sideElevation, sideElevation, sideElevation,
578 -sideElevation, -sideElevation, -sideElevation, -sideElevation,
579 };
580
582 45, 135, 225, 315, 45, 135, 225, 315,
583 };
584
585 cfg->m_CurrentPreset = aRenderJob->m_colorPreset;
586 boardAdapter.m_Cfg = cfg;
587
590 && aRenderJob->m_format == JOB_PCB_RENDER::FORMAT::PNG ) )
591 {
592 boardAdapter.m_ColorOverrides[LAYER_3D_BACKGROUND_TOP] = COLOR4D( 1.0, 1.0, 1.0, 0.0 );
593 boardAdapter.m_ColorOverrides[LAYER_3D_BACKGROUND_BOTTOM] = COLOR4D( 1.0, 1.0, 1.0, 0.0 );
594 }
595
597
598 static std::map<JOB_PCB_RENDER::SIDE, VIEW3D_TYPE> s_viewCmdMap = {
599 { JOB_PCB_RENDER::SIDE::TOP, VIEW3D_TYPE::VIEW3D_TOP },
600 { JOB_PCB_RENDER::SIDE::BOTTOM, VIEW3D_TYPE::VIEW3D_BOTTOM },
601 { JOB_PCB_RENDER::SIDE::LEFT, VIEW3D_TYPE::VIEW3D_LEFT },
602 { JOB_PCB_RENDER::SIDE::RIGHT, VIEW3D_TYPE::VIEW3D_RIGHT },
603 { JOB_PCB_RENDER::SIDE::FRONT, VIEW3D_TYPE::VIEW3D_FRONT },
604 { JOB_PCB_RENDER::SIDE::BACK, VIEW3D_TYPE::VIEW3D_BACK },
605 };
606
607 PROJECTION_TYPE projection = aRenderJob->m_perspective ? PROJECTION_TYPE::PERSPECTIVE
608 : PROJECTION_TYPE::ORTHO;
609
610 wxSize windowSize( aRenderJob->m_width, aRenderJob->m_height );
611 TRACK_BALL camera( 2 * RANGE_SCALE_3D );
612
613 camera.SetProjection( projection );
614 camera.SetCurWindowSize( windowSize );
615
616 RENDER_3D_RAYTRACE_RAM raytrace( boardAdapter, camera );
617 raytrace.SetCurWindowSize( windowSize );
618
619 for( bool first = true; raytrace.Redraw( false, m_reporter, m_reporter ); first = false )
620 {
621 if( first )
622 {
623 const float cmTo3D = boardAdapter.BiuTo3dUnits() * pcbIUScale.mmToIU( 10.0 );
624
625 // First redraw resets lookat point to the board center, so set up the camera here
626 camera.ViewCommand_T1( s_viewCmdMap[aRenderJob->m_side] );
627
628 camera.SetLookAtPos_T1(
629 camera.GetLookAtPos_T1()
630 + SFVEC3F( aRenderJob->m_pivot.x, aRenderJob->m_pivot.y, aRenderJob->m_pivot.z )
631 * cmTo3D );
632
633 camera.Pan_T1(
634 SFVEC3F( aRenderJob->m_pan.x, aRenderJob->m_pan.y, aRenderJob->m_pan.z ) );
635
636 camera.Zoom_T1( aRenderJob->m_zoom );
637
638 camera.RotateX_T1( DEG2RAD( aRenderJob->m_rotation.x ) );
639 camera.RotateY_T1( DEG2RAD( aRenderJob->m_rotation.y ) );
640 camera.RotateZ_T1( DEG2RAD( aRenderJob->m_rotation.z ) );
641
642 camera.Interpolate( 1.0f );
643 camera.SetT0_and_T1_current_T();
644 camera.ParametersChanged();
645 }
646 }
647
648 uint8_t* rgbaBuffer = raytrace.GetBuffer();
649 wxSize realSize = raytrace.GetRealBufferSize();
650 bool success = !!rgbaBuffer;
651
652 if( rgbaBuffer )
653 {
654 const unsigned int wxh = realSize.x * realSize.y;
655
656 unsigned char* rgbBuffer = (unsigned char*) malloc( wxh * 3 );
657 unsigned char* alphaBuffer = (unsigned char*) malloc( wxh );
658
659 unsigned char* rgbaPtr = rgbaBuffer;
660 unsigned char* rgbPtr = rgbBuffer;
661 unsigned char* alphaPtr = alphaBuffer;
662
663 for( int y = 0; y < realSize.y; y++ )
664 {
665 for( int x = 0; x < realSize.x; x++ )
666 {
667 rgbPtr[0] = rgbaPtr[0];
668 rgbPtr[1] = rgbaPtr[1];
669 rgbPtr[2] = rgbaPtr[2];
670 alphaPtr[0] = rgbaPtr[3];
671
672 rgbaPtr += 4;
673 rgbPtr += 3;
674 alphaPtr += 1;
675 }
676 }
677
678 wxImage image( realSize );
679 image.SetData( rgbBuffer );
680 image.SetAlpha( alphaBuffer );
681 image = image.Mirror( false );
682
683 image.SetOption( wxIMAGE_OPTION_QUALITY, 90 );
684 image.SaveFile( outPath,
685 aRenderJob->m_format == JOB_PCB_RENDER::FORMAT::PNG ? wxBITMAP_TYPE_PNG
686 : wxBITMAP_TYPE_JPEG );
687 }
688
689 if( success )
690 {
691 m_reporter->Report( _( "Successfully created 3D render image" ) + wxS( "\n" ),
693 }
694 else
695 {
696 m_reporter->Report( _( "Error creating 3D render image" ) + wxS( "\n" ),
698 }
699
700 return CLI::EXIT_CODES::OK;
701}
702
703
705{
706 JOB_EXPORT_PCB_SVG* aSvgJob = dynamic_cast<JOB_EXPORT_PCB_SVG*>( aJob );
707
708 if( aSvgJob == nullptr )
710
711 BOARD* brd = getBoard( aSvgJob->m_filename );
712
713 if( !brd )
715
716 aJob->SetTitleBlock( brd->GetTitleBlock() );
717
719 {
720 if( aSvgJob->GetConfiguredOutputPath().IsEmpty() )
721 {
722 wxFileName fn = brd->GetFileName();
723 fn.SetName( fn.GetName() );
724 fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::SVG ) );
725
726 aSvgJob->SetWorkingOutputPath( fn.GetFullName() );
727 }
728 }
729
730 wxString outPath = aSvgJob->GetFullOutputPath( brd->GetProject() );
731
733 {
734 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
736 }
737
739 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
741
742 PCB_PLOT_PARAMS plotOpts;
743 PCB_PLOTTER::PlotJobToPlotOpts( plotOpts, aSvgJob );
744
745 PCB_PLOTTER plotter( brd, m_reporter, plotOpts );
746
747 std::optional<wxString> layerName;
748 std::optional<wxString> sheetName;
749 std::optional<wxString> sheetPath;
750
752 {
753 if( aJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
754 layerName = aSvgJob->GetVarOverrides().at( wxT( "LAYER" ) );
755
756 if( aJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
757 sheetName = aSvgJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
758
759 if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
760 sheetPath = aSvgJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
761 }
762
763 if( !plotter.Plot( outPath, aSvgJob->m_printMaskLayer,
766 layerName,
767 sheetName,
768 sheetPath ) )
769 {
771 }
772
773 return CLI::EXIT_CODES::OK;
774}
775
776
778{
779 JOB_EXPORT_PCB_DXF* aDxfJob = dynamic_cast<JOB_EXPORT_PCB_DXF*>( aJob );
780
781 if( aDxfJob == nullptr )
783
784 BOARD* brd = getBoard( aDxfJob->m_filename );
785
786 if( !brd )
788
789 aJob->SetTitleBlock( brd->GetTitleBlock() );
791 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
793
794
796 {
797 if( aDxfJob->GetConfiguredOutputPath().IsEmpty() )
798 {
799 wxFileName fn = brd->GetFileName();
800 fn.SetName( fn.GetName() );
801 fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::DXF ) );
802
803 aDxfJob->SetWorkingOutputPath( fn.GetFullName() );
804 }
805 }
806
807 wxString outPath = aDxfJob->GetFullOutputPath( brd->GetProject() );
808
810 {
811 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
813 }
814
815 PCB_PLOT_PARAMS plotOpts;
816 PCB_PLOTTER::PlotJobToPlotOpts( plotOpts, aDxfJob );
817
818 PCB_PLOTTER plotter( brd, m_reporter, plotOpts );
819
820 std::optional<wxString> layerName;
821 std::optional<wxString> sheetName;
822 std::optional<wxString> sheetPath;
823
825 {
826 if( aJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
827 layerName = aDxfJob->GetVarOverrides().at( wxT( "LAYER" ) );
828
829 if( aJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
830 sheetName = aDxfJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
831
832 if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
833 sheetPath = aDxfJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
834 }
835
836 if( !plotter.Plot( outPath, aDxfJob->m_printMaskLayer,
838 aDxfJob->m_genMode == JOB_EXPORT_PCB_DXF::GEN_MODE::SINGLE, layerName,
839 sheetName, sheetPath ) )
840 {
842 }
843
844 return CLI::EXIT_CODES::OK;
845}
846
847
849{
850 JOB_EXPORT_PCB_PDF* aPdfJob = dynamic_cast<JOB_EXPORT_PCB_PDF*>( aJob );
851
852 if( aPdfJob == nullptr )
854
855 BOARD* brd = getBoard( aPdfJob->m_filename );
856
857 if( !brd )
859
860 aJob->SetTitleBlock( brd->GetTitleBlock() );
862 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
864
866 && aPdfJob->GetConfiguredOutputPath().IsEmpty() )
867 {
868 wxFileName fn = brd->GetFileName();
869 fn.SetName( fn.GetName() );
870 fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::PDF ) );
871
872 aPdfJob->SetWorkingOutputPath( fn.GetFullName() );
873 }
874
875 PCB_PLOT_PARAMS plotOpts;
876 PCB_PLOTTER::PlotJobToPlotOpts( plotOpts, aPdfJob );
877
878 int returnCode = CLI::EXIT_CODES::OK;
879
880 // ensure this is set for this one gen mode
882 {
883 plotOpts.m_PDFSingle = true;
884 }
885
886 PCB_PLOTTER pcbPlotter( brd, m_reporter, plotOpts );
887
888 wxString outPath = aPdfJob->GetFullOutputPath( brd->GetProject() );
889
891 {
892 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
894 }
895
896 std::optional<wxString> layerName;
897 std::optional<wxString> sheetName;
898 std::optional<wxString> sheetPath;
900 {
901 if( aPdfJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
902 layerName = aPdfJob->GetVarOverrides().at( wxT( "LAYER" ) );
903
904 if( aPdfJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
905 sheetName = aPdfJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
906
907 if( aPdfJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
908 sheetPath = aPdfJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
909 }
910
911
913 if( !pcbPlotter.Plot( outPath, aPdfJob->m_printMaskLayer,
915 false,
917 layerName,
918 sheetName,
919 sheetPath ) )
920 {
921 returnCode = CLI::EXIT_CODES::ERR_UNKNOWN;
922 }
923
924 return returnCode;
925}
926
927
929{
930 int exitCode = CLI::EXIT_CODES::OK;
931 JOB_EXPORT_PCB_GERBERS* aGerberJob = dynamic_cast<JOB_EXPORT_PCB_GERBERS*>( aJob );
932
933 if( aGerberJob == nullptr )
935
936 BOARD* brd = getBoard( aGerberJob->m_filename );
937
938 if( !brd )
940
941 wxString outPath = aGerberJob->GetFullOutputPath( brd->GetProject() );
942
943 if( !PATHS::EnsurePathExists( outPath, false ) )
944 {
945 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
947 }
948
949 aJob->SetTitleBlock( brd->GetTitleBlock() );
950 loadOverrideDrawingSheet( brd, aGerberJob->m_drawingSheet );
951 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
953
954 PCB_PLOT_PARAMS boardPlotOptions = brd->GetPlotOptions();
955 LSET plotOnAllLayersSelection = boardPlotOptions.GetPlotOnAllLayersSelection();
956 GERBER_JOBFILE_WRITER jobfile_writer( brd );
957
958 wxString fileExt;
959
960 if( aGerberJob->m_useBoardPlotParams )
961 {
962 // The board plot options are saved with all copper layers enabled, even those that don't
963 // exist in the current stackup. This is done so the layers are automatically enabled in the plot
964 // dialog when the user enables them. We need to filter out these not-enabled layers here so
965 // we don't plot 32 layers when we only have 4, etc.
966 LSET plotLayers = ( boardPlotOptions.GetLayerSelection() & LSET::AllNonCuMask() )
967 | ( brd->GetEnabledLayers() & LSET::AllCuMask() );
968 aGerberJob->m_printMaskLayer = plotLayers.SeqStackupForPlotting();
969 aGerberJob->m_layersIncludeOnAll = boardPlotOptions.GetPlotOnAllLayersSelection().UIOrder();
970 }
971 else
972 {
973 // default to the board enabled layers
974 if( aGerberJob->m_printMaskLayer.empty() )
976
977 if( aGerberJob->m_layersIncludeOnAllSet )
978 aGerberJob->m_layersIncludeOnAll = plotOnAllLayersSelection.UIOrder();
979 }
980
981 // Ensure layers to plot are restricted to enabled layers of the board to plot
982 LSET layersToPlot = LSET( { aGerberJob->m_printMaskLayer } ) & brd->GetEnabledLayers();
983
984 for( PCB_LAYER_ID layer : layersToPlot.UIOrder() )
985 {
986 LSEQ plotSequence;
987
988 // Base layer always gets plotted first.
989 plotSequence.push_back( layer );
990
991 // Now all the "include on all" layers
992 for( PCB_LAYER_ID layer_all : aGerberJob->m_layersIncludeOnAll )
993 {
994 // Don't plot the same layer more than once;
995 if( find( plotSequence.begin(), plotSequence.end(), layer_all ) != plotSequence.end() )
996 continue;
997
998 plotSequence.push_back( layer_all );
999 }
1000
1001 // Pick the basename from the board file
1002 wxFileName fn( brd->GetFileName() );
1003 wxString layerName = brd->GetLayerName( layer );
1004 wxString sheetName;
1005 wxString sheetPath;
1006 PCB_PLOT_PARAMS plotOpts;
1007
1008 if( aGerberJob->m_useBoardPlotParams )
1009 plotOpts = boardPlotOptions;
1010 else
1011 populateGerberPlotOptionsFromJob( plotOpts, aGerberJob );
1012
1013 if( plotOpts.GetUseGerberProtelExtensions() )
1014 fileExt = GetGerberProtelExtension( layer );
1015 else
1017
1018 BuildPlotFileName( &fn, outPath, layerName, fileExt );
1019 wxString fullname = fn.GetFullName();
1020
1021 jobfile_writer.AddGbrFile( layer, fullname );
1022
1023 if( aJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
1024 layerName = aJob->GetVarOverrides().at( wxT( "LAYER" ) );
1025
1026 if( aJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
1027 sheetName = aJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
1028
1029 if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
1030 sheetPath = aJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
1031
1032 // We are feeding it one layer at the start here to silence a logic check
1033 GERBER_PLOTTER* plotter;
1034 {
1036 plotter = (GERBER_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer, layerName,
1037 fn.GetFullPath(), sheetName, sheetPath );
1038 }
1039
1040 if( plotter )
1041 {
1042 m_reporter->Report( wxString::Format( _( "Plotted to '%s'.\n" ), fn.GetFullPath() ),
1045 PlotBoardLayers( brd, plotter, plotSequence, plotOpts );
1046 plotter->EndPlot();
1047 }
1048 else
1049 {
1050 m_reporter->Report( wxString::Format( _( "Failed to plot to '%s'.\n" ),
1051 fn.GetFullPath() ),
1054 }
1055
1056 delete plotter;
1057 }
1058
1059 wxFileName fn( brd->GetFileName() );
1060
1061 // Build gerber job file from basename
1062 BuildPlotFileName( &fn, outPath, wxT( "job" ), FILEEXT::GerberJobFileExtension );
1063 jobfile_writer.CreateJobFile( fn.GetFullPath() );
1064
1065 return exitCode;
1066}
1067
1069{
1070 JOB_EXPORT_PCB_GENCAD* aGencadJob = dynamic_cast<JOB_EXPORT_PCB_GENCAD*>( aJob );
1071
1072 if( aGencadJob == nullptr )
1074
1075 BOARD* brd = LoadBoard( aGencadJob->m_filename, true ); // Ensure m_board is of type BOARD*
1076
1077 if( brd == nullptr )
1079
1080 GENCAD_EXPORTER exporter( brd );
1081
1082 VECTOR2I GencadOffset;
1083 VECTOR2I auxOrigin = brd->GetDesignSettings().GetAuxOrigin();
1084 GencadOffset.x = aGencadJob->m_useDrillOrigin ? auxOrigin.x : 0;
1085 GencadOffset.y = aGencadJob->m_useDrillOrigin ? auxOrigin.y : 0;
1086
1087 exporter.FlipBottomPads( aGencadJob->m_flipBottomPads );
1088 exporter.UsePinNamesUnique( aGencadJob->m_useUniquePins );
1089 exporter.UseIndividualShapes( aGencadJob->m_useIndividualShapes );
1090 exporter.SetPlotOffet( GencadOffset );
1091 exporter.StoreOriginCoordsInFile( aGencadJob->m_storeOriginCoords );
1092
1093 if( aGencadJob->GetConfiguredOutputPath().IsEmpty() )
1094 {
1095 wxFileName fn = brd->GetFileName();
1096 fn.SetName( fn.GetName() );
1097 fn.SetExt( FILEEXT::GencadFileExtension );
1098
1099 aGencadJob->SetWorkingOutputPath( fn.GetFullName() );
1100 }
1101
1102 wxString outPath = aGencadJob->GetFullOutputPath( brd->GetProject() );
1103
1104 if( !PATHS::EnsurePathExists( outPath, true ) )
1105 {
1106 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
1108 }
1109
1110 if( !exporter.WriteFile( outPath ) )
1111 {
1112 m_reporter->Report( wxString::Format( _( "Failed to create file '%s'.\n" ), outPath ),
1114
1116 }
1117
1118 m_reporter->Report( _( "Successfully created genCAD file\n" ), RPT_SEVERITY_INFO );
1119
1120 return CLI::EXIT_CODES::OK;
1121}
1122
1123
1125 JOB_EXPORT_PCB_GERBER* aJob )
1126{
1127 aPlotOpts.SetFormat( PLOT_FORMAT::GERBER );
1128
1129 aPlotOpts.SetPlotFrameRef( aJob->m_plotDrawingSheet );
1130 aPlotOpts.SetPlotValue( aJob->m_plotFootprintValues );
1131 aPlotOpts.SetPlotReference( aJob->m_plotRefDes );
1132
1134
1135 // Always disable plot pad holes
1136 aPlotOpts.SetDrillMarksType( DRILL_MARKS::NO_DRILL_SHAPE );
1137
1139 aPlotOpts.SetUseGerberX2format( aJob->m_useX2Format );
1141 aPlotOpts.SetUseAuxOrigin( aJob->m_useDrillOrigin );
1143 aPlotOpts.SetGerberPrecision( aJob->m_precision );
1144}
1145
1146
1148{
1149 int exitCode = CLI::EXIT_CODES::OK;
1150 JOB_EXPORT_PCB_GERBER* aGerberJob = dynamic_cast<JOB_EXPORT_PCB_GERBER*>( aJob );
1151
1152 if( aGerberJob == nullptr )
1154
1155 BOARD* brd = getBoard( aGerberJob->m_filename );
1156
1157 if( !brd )
1159
1160 aJob->SetTitleBlock( brd->GetTitleBlock() );
1161 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
1162 brd->SynchronizeProperties();
1163
1164 if( aGerberJob->GetConfiguredOutputPath().IsEmpty() )
1165 {
1166 wxFileName fn = brd->GetFileName();
1167 fn.SetName( fn.GetName() );
1168 fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::GERBER ) );
1169
1170 aGerberJob->SetWorkingOutputPath( fn.GetFullName() );
1171 }
1172
1173 PCB_PLOT_PARAMS plotOpts;
1174 populateGerberPlotOptionsFromJob( plotOpts, aGerberJob );
1175 plotOpts.SetLayerSelection( aGerberJob->m_printMaskLayer );
1177
1179 wxString layerName;
1180 wxString sheetName;
1181 wxString sheetPath;
1182
1183 // The first layer will be treated as the layer name for the gerber header,
1184 // the other layers will be treated equivalent to the "Plot on All Layers" option
1185 // in the GUI
1186 if( aGerberJob->m_printMaskLayer.size() >= 1 )
1187 {
1188 layer = aGerberJob->m_printMaskLayer.front();
1189 layerName = brd->GetLayerName( layer );
1190 }
1191
1192 if( aJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
1193 layerName = aJob->GetVarOverrides().at( wxT( "LAYER" ) );
1194
1195 if( aJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
1196 sheetName = aJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
1197
1198 if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
1199 sheetPath = aJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
1200
1201 // We are feeding it one layer at the start here to silence a logic check
1202 GERBER_PLOTTER* plotter = (GERBER_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer, layerName,
1203 aGerberJob->GetFullOutputPath( brd->GetProject() ),
1204 sheetName, sheetPath );
1205
1206 if( plotter )
1207 {
1208 PlotBoardLayers( brd, plotter, aGerberJob->m_printMaskLayer, plotOpts );
1209 plotter->EndPlot();
1210 }
1211 else
1212 {
1213 m_reporter->Report( wxString::Format( _( "Failed to plot to '%s'.\n" ),
1214 aGerberJob->GetFullOutputPath( brd->GetProject() ) ),
1217 }
1218
1219 delete plotter;
1220
1221 return exitCode;
1222}
1223
1226
1227
1229{
1230 JOB_EXPORT_PCB_DRILL* aDrillJob = dynamic_cast<JOB_EXPORT_PCB_DRILL*>( aJob );
1231
1232 if( aDrillJob == nullptr )
1234
1235 BOARD* brd = getBoard( aDrillJob->m_filename );
1236
1237 if( !brd )
1239
1240 aJob->SetTitleBlock( brd->GetTitleBlock() );
1241
1242 wxString outPath = aDrillJob->GetFullOutputPath( brd->GetProject() );
1243
1244 if( !PATHS::EnsurePathExists( outPath ) )
1245 {
1246 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
1248 }
1249
1250 std::unique_ptr<GENDRILL_WRITER_BASE> drillWriter;
1251
1253 drillWriter = std::make_unique<EXCELLON_WRITER>( brd );
1254 else
1255 drillWriter = std::make_unique<GERBER_WRITER>( brd );
1256
1257 VECTOR2I offset;
1258
1260 offset = VECTOR2I( 0, 0 );
1261 else
1262 offset = brd->GetDesignSettings().GetAuxOrigin();
1263
1264 PLOT_FORMAT mapFormat = PLOT_FORMAT::PDF;
1265
1266 switch( aDrillJob->m_mapFormat )
1267 {
1268 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::POSTSCRIPT: mapFormat = PLOT_FORMAT::POST; break;
1269 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::GERBER_X2: mapFormat = PLOT_FORMAT::GERBER; break;
1270 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::DXF: mapFormat = PLOT_FORMAT::DXF; break;
1271 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::SVG: mapFormat = PLOT_FORMAT::SVG; break;
1272 default:
1273 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::PDF: mapFormat = PLOT_FORMAT::PDF; break;
1274 }
1275
1277 {
1279 switch( aDrillJob->m_zeroFormat )
1280 {
1283 break;
1286 break;
1289 break;
1291 default:
1293 break;
1294 }
1295
1296 DRILL_PRECISION precision;
1297
1299 precision = precisionListForInches;
1300 else
1301 precision = precisionListForMetric;
1302
1303 EXCELLON_WRITER* excellonWriter = dynamic_cast<EXCELLON_WRITER*>( drillWriter.get() );
1304
1305 if( excellonWriter == nullptr )
1307
1308 excellonWriter->SetFormat( aDrillJob->m_drillUnits
1310 zeroFmt, precision.m_Lhs, precision.m_Rhs );
1311 excellonWriter->SetOptions( aDrillJob->m_excellonMirrorY,
1312 aDrillJob->m_excellonMinimalHeader,
1313 offset, aDrillJob->m_excellonCombinePTHNPTH );
1314 excellonWriter->SetRouteModeForOvalHoles( aDrillJob->m_excellonOvalDrillRoute );
1315 excellonWriter->SetMapFileFormat( mapFormat );
1316
1317 if( !excellonWriter->CreateDrillandMapFilesSet( outPath, true, aDrillJob->m_generateMap,
1318 m_reporter ) )
1319 {
1321 }
1322 }
1324 {
1325 GERBER_WRITER* gerberWriter = dynamic_cast<GERBER_WRITER*>( drillWriter.get() );
1326
1327 if( gerberWriter == nullptr )
1329
1330 // Set gerber precision: only 5 or 6 digits for mantissa are allowed
1331 // (SetFormat() accept 5 or 6, and any other value set the precision to 5)
1332 // the integer part precision is always 4, and units always mm
1333 gerberWriter->SetFormat( aDrillJob->m_gerberPrecision );
1334 gerberWriter->SetOptions( offset );
1335 gerberWriter->SetMapFileFormat( mapFormat );
1336
1337 if( !gerberWriter->CreateDrillandMapFilesSet( outPath, true, aDrillJob->m_generateMap,
1338 m_reporter ) )
1339 {
1341 }
1342 }
1343
1344 return CLI::EXIT_CODES::OK;
1345}
1346
1347
1349{
1350 JOB_EXPORT_PCB_POS* aPosJob = dynamic_cast<JOB_EXPORT_PCB_POS*>( aJob );
1351
1352 if( aPosJob == nullptr )
1354
1355 BOARD* brd = getBoard( aPosJob->m_filename );
1356
1357 if( !brd )
1359
1360 aJob->SetTitleBlock( brd->GetTitleBlock() );
1361
1362 if( aPosJob->GetConfiguredOutputPath().IsEmpty() )
1363 {
1364 wxFileName fn = brd->GetFileName();
1365 fn.SetName( fn.GetName() );
1366
1369 else if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV )
1370 fn.SetExt( FILEEXT::CsvFileExtension );
1371 else if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::GERBER )
1372 fn.SetExt( FILEEXT::GerberFileExtension );
1373
1374 aPosJob->SetWorkingOutputPath( fn.GetFullName() );
1375 }
1376
1377 wxString outPath = aPosJob->GetFullOutputPath( brd->GetProject() );
1378
1379 if( !PATHS::EnsurePathExists( outPath, true ) )
1380 {
1381 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
1383 }
1384
1387 {
1388 wxFileName fn( outPath );
1389 wxString baseName = fn.GetName();
1390
1391 auto exportPlaceFile =
1392 [&]( bool frontSide, bool backSide, const wxString& curr_outPath ) -> bool
1393 {
1394 FILE* file = wxFopen( curr_outPath, wxS( "wt" ) );
1395 wxCHECK( file, false );
1396
1397 PLACE_FILE_EXPORTER exporter( brd,
1399 aPosJob->m_smdOnly,
1401 aPosJob->m_excludeDNP,
1402 frontSide,
1403 backSide,
1406 aPosJob->m_negateBottomX );
1407
1408 std::string data = exporter.GenPositionData();
1409 fputs( data.c_str(), file );
1410 fclose( file );
1411
1412 return true;
1413 };
1414
1415 if( aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH && !aPosJob->m_singleFile )
1416 {
1417 fn.SetName( PLACE_FILE_EXPORTER::DecorateFilename( baseName, true, false ) );
1418
1419 if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV && !aPosJob->m_nakedFilename )
1420 fn.SetName( fn.GetName() + wxT( "-" ) + FILEEXT::FootprintPlaceFileExtension );
1421
1422 if( exportPlaceFile( true, false, fn.GetFullPath() ) )
1423 {
1424 m_reporter->Report( wxString::Format( _( "Wrote front position data to '%s'.\n" ),
1425 fn.GetFullPath() ),
1427
1428 aPosJob->AddOutput( fn.GetFullPath() );
1429 }
1430 else
1431 {
1433 }
1434
1435 fn.SetName( PLACE_FILE_EXPORTER::DecorateFilename( baseName, false, true ) );
1436
1437 if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV && !aPosJob->m_nakedFilename )
1438 fn.SetName( fn.GetName() + wxT( "-" ) + FILEEXT::FootprintPlaceFileExtension );
1439
1440 if( exportPlaceFile( false, true, fn.GetFullPath() ) )
1441 {
1442 m_reporter->Report( wxString::Format( _( "Wrote back position data to '%s'.\n" ),
1443 fn.GetFullPath() ),
1445
1446 aPosJob->AddOutput( fn.GetFullPath() );
1447 }
1448 else
1449 {
1451 }
1452 }
1453 else
1454 {
1455 bool front = aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::FRONT
1457
1458 bool back = aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BACK
1460
1461 if( !aPosJob->m_nakedFilename )
1462 {
1463 fn.SetName( PLACE_FILE_EXPORTER::DecorateFilename( fn.GetName(), front, back ) );
1464
1466 fn.SetName( fn.GetName() + wxT( "-" ) + FILEEXT::FootprintPlaceFileExtension );
1467 }
1468
1469 if( exportPlaceFile( front, back, fn.GetFullPath() ) )
1470 {
1471 m_reporter->Report( wxString::Format( _( "Wrote position data to '%s'.\n" ),
1472 fn.GetFullPath() ),
1474
1475 aPosJob->AddOutput( fn.GetFullPath() );
1476 }
1477 else
1478 {
1480 }
1481 }
1482 }
1483 else if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::GERBER )
1484 {
1485 PLACEFILE_GERBER_WRITER exporter( brd );
1486 PCB_LAYER_ID gbrLayer = F_Cu;
1487 wxString outPath_base = outPath;
1488
1490 || aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH )
1491 {
1492 if( aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH || !aPosJob->m_nakedFilename )
1493 outPath = exporter.GetPlaceFileName( outPath, gbrLayer );
1494
1495 if( exporter.CreatePlaceFile( outPath, gbrLayer, aPosJob->m_gerberBoardEdge ) >= 0 )
1496 {
1497 m_reporter->Report( wxString::Format( _( "Wrote front position data to '%s'.\n" ),
1498 outPath ),
1500
1501 aPosJob->AddOutput( outPath );
1502 }
1503 else
1504 {
1506 }
1507 }
1508
1510 || aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH )
1511 {
1512 gbrLayer = B_Cu;
1513
1514 outPath = outPath_base;
1515
1516 if( aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH || !aPosJob->m_nakedFilename )
1517 outPath = exporter.GetPlaceFileName( outPath, gbrLayer );
1518
1519 if( exporter.CreatePlaceFile( outPath, gbrLayer, aPosJob->m_gerberBoardEdge ) >= 0 )
1520 {
1521 m_reporter->Report( wxString::Format( _( "Wrote back position data to '%s'.\n" ),
1522 outPath ),
1524
1525 aPosJob->AddOutput( outPath );
1526 }
1527 else
1528 {
1530 }
1531 }
1532 }
1533
1534 return CLI::EXIT_CODES::OK;
1535}
1536
1537extern FOOTPRINT* try_load_footprint( const wxFileName& aFileName, PCB_IO_MGR::PCB_FILE_T aFileType,
1538 const wxString& aName );
1539
1540
1542{
1543 JOB_FP_UPGRADE* upgradeJob = dynamic_cast<JOB_FP_UPGRADE*>( aJob );
1544
1545 if( upgradeJob == nullptr )
1547
1549
1550 if( !upgradeJob->m_outputLibraryPath.IsEmpty() )
1551 {
1552 if( wxFile::Exists( upgradeJob->m_outputLibraryPath )
1553 || wxDir::Exists( upgradeJob->m_outputLibraryPath) )
1554 {
1555 m_reporter->Report( _( "Output path must not conflict with existing path\n" ),
1558 }
1559 }
1560 else if( fileType != PCB_IO_MGR::KICAD_SEXP )
1561 {
1562 m_reporter->Report( _( "Output path must be specified to convert legacy and non-KiCad libraries\n" ),
1564
1566 }
1567
1569 {
1570 if( !wxDir::Exists( upgradeJob->m_libraryPath ) )
1571 {
1572 m_reporter->Report( _( "Footprint library path does not exist or is not accessible\n" ),
1575 }
1576
1578 FP_CACHE fpLib( &pcb_io, upgradeJob->m_libraryPath );
1579
1580 try
1581 {
1582 fpLib.Load();
1583 }
1584 catch( ... )
1585 {
1586 m_reporter->Report( _( "Unable to load library\n" ), RPT_SEVERITY_ERROR );
1588 }
1589
1590 bool shouldSave = upgradeJob->m_force;
1591
1592 for( const auto& footprint : fpLib.GetFootprints() )
1593 {
1594 if( footprint.second->GetFootprint()->GetFileFormatVersionAtLoad()
1596 {
1597 shouldSave = true;
1598 }
1599 }
1600
1601 if( shouldSave )
1602 {
1603 try
1604 {
1605 if( !upgradeJob->m_outputLibraryPath.IsEmpty() )
1606 fpLib.SetPath( upgradeJob->m_outputLibraryPath );
1607
1608 fpLib.Save();
1609 }
1610 catch( ... )
1611 {
1612 m_reporter->Report( _( "Unable to save library\n" ), RPT_SEVERITY_ERROR );
1614 }
1615 }
1616 else
1617 {
1618 m_reporter->Report( _( "Footprint library was not updated\n" ), RPT_SEVERITY_ERROR );
1619 }
1620 }
1621 else
1622 {
1623 if( !PCB_IO_MGR::ConvertLibrary( nullptr, upgradeJob->m_libraryPath,
1624 upgradeJob->m_outputLibraryPath, nullptr /* REPORTER */ ) )
1625 {
1626 m_reporter->Report( ( "Unable to convert library\n" ), RPT_SEVERITY_ERROR );
1628 }
1629 }
1630
1631 return CLI::EXIT_CODES::OK;
1632}
1633
1634
1636{
1637 JOB_FP_EXPORT_SVG* svgJob = dynamic_cast<JOB_FP_EXPORT_SVG*>( aJob );
1638
1639 if( svgJob == nullptr )
1641
1643 FP_CACHE fpLib( &pcb_io, svgJob->m_libraryPath );
1644
1645 try
1646 {
1647 fpLib.Load();
1648 }
1649 catch( ... )
1650 {
1651 m_reporter->Report( _( "Unable to load library\n" ), RPT_SEVERITY_ERROR );
1653 }
1654
1655 if( !svgJob->m_outputDirectory.IsEmpty() && !wxDir::Exists( svgJob->m_outputDirectory ) )
1656 {
1657 wxFileName::Mkdir( svgJob->m_outputDirectory );
1658 }
1659
1660 int exitCode = CLI::EXIT_CODES::OK;
1661
1662 // Just plot all the symbols we can
1663 FP_CACHE_FOOTPRINT_MAP& footprintMap = fpLib.GetFootprints();
1664
1665 bool singleFpPlotted = false;
1666 for( FP_CACHE_FOOTPRINT_MAP::iterator it = footprintMap.begin(); it != footprintMap.end();
1667 ++it )
1668 {
1669 const FOOTPRINT* fp = it->second->GetFootprint();
1670 if( !svgJob->m_footprint.IsEmpty() )
1671 {
1672 if( fp->GetFPID().GetLibItemName().wx_str() != svgJob->m_footprint )
1673 {
1674 // skip until we find the right footprint
1675 continue;
1676 }
1677 else
1678 {
1679 singleFpPlotted = true;
1680 }
1681 }
1682
1683 exitCode = doFpExportSvg( svgJob, fp );
1684 if( exitCode != CLI::EXIT_CODES::OK )
1685 break;
1686 }
1687
1688 if( !svgJob->m_footprint.IsEmpty() && !singleFpPlotted )
1689 {
1690 m_reporter->Report( _( "The given footprint could not be found to export." ) + wxS( "\n" ),
1692 }
1693
1694 return CLI::EXIT_CODES::OK;
1695}
1696
1697
1699{
1700 // the hack for now is we create fake boards containing the footprint and plot the board
1701 // until we refactor better plot api later
1702 std::unique_ptr<BOARD> brd;
1703 brd.reset( CreateEmptyBoard() );
1704 brd->GetProject()->ApplyTextVars( aSvgJob->GetVarOverrides() );
1705 brd->SynchronizeProperties();
1706
1707 FOOTPRINT* fp = dynamic_cast<FOOTPRINT*>( aFootprint->Clone() );
1708
1709 if( fp == nullptr )
1711
1712 fp->SetLink( niluuid );
1713 fp->SetFlags( IS_NEW );
1714 fp->SetParent( brd.get() );
1715
1716 for( PAD* pad : fp->Pads() )
1717 {
1718 pad->SetLocalRatsnestVisible( false );
1719 pad->SetNetCode( 0 );
1720 }
1721
1722 fp->SetOrientation( ANGLE_0 );
1723 fp->SetPosition( VECTOR2I( 0, 0 ) );
1724
1725 brd->Add( fp, ADD_MODE::INSERT, true );
1726
1727 wxFileName outputFile;
1728 outputFile.SetPath( aSvgJob->m_outputDirectory );
1729 outputFile.SetName( aFootprint->GetFPID().GetLibItemName().wx_str() );
1730 outputFile.SetExt( FILEEXT::SVGFileExtension );
1731
1732 m_reporter->Report( wxString::Format( _( "Plotting footprint '%s' to '%s'\n" ),
1733 aFootprint->GetFPID().GetLibItemName().wx_str(),
1734 outputFile.GetFullPath() ),
1736
1737
1738 PCB_PLOT_SVG_OPTIONS svgPlotOptions;
1739 svgPlotOptions.m_blackAndWhite = aSvgJob->m_blackAndWhite;
1740 svgPlotOptions.m_colorTheme = aSvgJob->m_colorTheme;
1741 svgPlotOptions.m_outputFile = outputFile.GetFullPath();
1742 svgPlotOptions.m_mirror = false;
1743 svgPlotOptions.m_pageSizeMode = 2; // board bounding box
1744 svgPlotOptions.m_printMaskLayer = aSvgJob->m_printMaskLayer;
1745 svgPlotOptions.m_sketchPadsOnFabLayers = aSvgJob->m_sketchPadsOnFabLayers;
1746 svgPlotOptions.m_hideDNPFPsOnFabLayers = aSvgJob->m_hideDNPFPsOnFabLayers;
1747 svgPlotOptions.m_sketchDNPFPsOnFabLayers = aSvgJob->m_sketchDNPFPsOnFabLayers;
1749 svgPlotOptions.m_plotFrame = false;
1750
1751 if( !EXPORT_SVG::Plot( brd.get(), svgPlotOptions ) )
1752 m_reporter->Report( _( "Error creating svg file" ) + wxS( "\n" ), RPT_SEVERITY_ERROR );
1753
1754 return CLI::EXIT_CODES::OK;
1755}
1756
1757
1759{
1760 JOB_PCB_DRC* drcJob = dynamic_cast<JOB_PCB_DRC*>( aJob );
1761
1762 if( drcJob == nullptr )
1764
1765 BOARD* brd = getBoard( drcJob->m_filename );
1766
1767 if( !brd )
1769
1770 aJob->SetTitleBlock( brd->GetTitleBlock() );
1771 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
1772 brd->SynchronizeProperties();
1773
1774 if( drcJob->GetConfiguredOutputPath().IsEmpty() )
1775 {
1776 wxFileName fn = brd->GetFileName();
1777 fn.SetName( fn.GetName() + wxS( "-drc" ) );
1778
1780 fn.SetExt( FILEEXT::JsonFileExtension );
1781 else
1782 fn.SetExt( FILEEXT::ReportFileExtension );
1783
1784 drcJob->SetWorkingOutputPath( fn.GetFullName() );
1785 }
1786
1787 wxString outPath = drcJob->GetFullOutputPath( brd->GetProject() );
1788
1789 if( !PATHS::EnsurePathExists( outPath, true ) )
1790 {
1791 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
1793 }
1794
1795 EDA_UNITS units;
1796
1797 switch( drcJob->m_units )
1798 {
1799 case JOB_PCB_DRC::UNITS::INCHES: units = EDA_UNITS::INCHES; break;
1800 case JOB_PCB_DRC::UNITS::MILS: units = EDA_UNITS::MILS; break;
1801 case JOB_PCB_DRC::UNITS::MILLIMETERS: units = EDA_UNITS::MILLIMETRES; break;
1802 default: units = EDA_UNITS::MILLIMETRES; break;
1803 }
1804
1805 std::shared_ptr<DRC_ENGINE> drcEngine = brd->GetDesignSettings().m_DRCEngine;
1806 std::unique_ptr<NETLIST> netlist = std::make_unique<NETLIST>();
1807
1808 drcEngine->SetDrawingSheet( getDrawingSheetProxyView( brd ) );
1809
1810 // BOARD_COMMIT uses TOOL_MANAGER to grab the board internally so we must give it one
1811 TOOL_MANAGER* toolManager = new TOOL_MANAGER;
1812 toolManager->SetEnvironment( brd, nullptr, nullptr, Kiface().KifaceSettings(), nullptr );
1813
1814 BOARD_COMMIT commit( toolManager );
1815 bool checkParity = drcJob->m_parity;
1816 std::string netlist_str;
1817
1818 if( checkParity )
1819 {
1820 wxString annotateMsg = _( "Schematic parity tests require a fully annotated schematic." );
1821 netlist_str = annotateMsg;
1822
1824
1825 if( netlist_str == annotateMsg )
1826 {
1827 m_reporter->Report( netlist_str + wxT( "\n" ), RPT_SEVERITY_ERROR );
1828 checkParity = false;
1829 }
1830 }
1831
1832 if( checkParity )
1833 {
1834 try
1835 {
1836 STRING_LINE_READER* lineReader = new STRING_LINE_READER( netlist_str,
1837 _( "Eeschema netlist" ) );
1838 KICAD_NETLIST_READER netlistReader( lineReader, netlist.get() );
1839
1840 netlistReader.LoadNetlist();
1841 }
1842 catch( const IO_ERROR& )
1843 {
1844 m_reporter->Report( _( "Failed to fetch schematic netlist for parity tests.\n" ),
1846 checkParity = false;
1847 }
1848
1849 drcEngine->SetSchematicNetlist( netlist.get() );
1850 }
1851
1852 drcEngine->SetProgressReporter( nullptr );
1853 drcEngine->SetViolationHandler(
1854 [&]( const std::shared_ptr<DRC_ITEM>& aItem, VECTOR2I aPos, int aLayer,
1855 DRC_CUSTOM_MARKER_HANDLER* aCustomHandler )
1856 {
1857 PCB_MARKER* marker = new PCB_MARKER( aItem, aPos, aLayer );
1858 commit.Add( marker );
1859 } );
1860
1861 brd->RecordDRCExclusions();
1862 brd->DeleteMARKERs( true, true );
1863 drcEngine->RunTests( units, drcJob->m_reportAllTrackErrors, checkParity );
1864 drcEngine->ClearViolationHandler();
1865
1866 commit.Push( _( "DRC" ), SKIP_UNDO | SKIP_SET_DIRTY );
1867
1868 // Update the exclusion status on any excluded markers that still exist.
1869 brd->ResolveDRCExclusions( false );
1870
1871 std::shared_ptr<DRC_ITEMS_PROVIDER> markersProvider = std::make_shared<DRC_ITEMS_PROVIDER>(
1873
1874 std::shared_ptr<DRC_ITEMS_PROVIDER> ratsnestProvider =
1875 std::make_shared<DRC_ITEMS_PROVIDER>( brd, MARKER_BASE::MARKER_RATSNEST );
1876
1877 std::shared_ptr<DRC_ITEMS_PROVIDER> fpWarningsProvider =
1878 std::make_shared<DRC_ITEMS_PROVIDER>( brd, MARKER_BASE::MARKER_PARITY );
1879
1880 markersProvider->SetSeverities( drcJob->m_severity );
1881 ratsnestProvider->SetSeverities( drcJob->m_severity );
1882 fpWarningsProvider->SetSeverities( drcJob->m_severity );
1883
1884 m_reporter->Report( wxString::Format( _( "Found %d violations\n" ),
1885 markersProvider->GetCount() ),
1887 m_reporter->Report( wxString::Format( _( "Found %d unconnected items\n" ),
1888 ratsnestProvider->GetCount() ),
1890
1891 if( checkParity )
1892 {
1893 m_reporter->Report( wxString::Format( _( "Found %d schematic parity issues\n" ),
1894 fpWarningsProvider->GetCount() ),
1896 }
1897
1898 DRC_REPORT reportWriter( brd, units, markersProvider, ratsnestProvider, fpWarningsProvider );
1899
1900 bool wroteReport = false;
1901
1903 wroteReport = reportWriter.WriteJsonReport( outPath );
1904 else
1905 wroteReport = reportWriter.WriteTextReport( outPath );
1906
1907 if( !wroteReport )
1908 {
1909 m_reporter->Report( wxString::Format( _( "Unable to save DRC report to %s\n" ), outPath ),
1912 }
1913
1914 m_reporter->Report( wxString::Format( _( "Saved DRC Report to %s\n" ), outPath ),
1916
1917 if( drcJob->m_exitCodeViolations )
1918 {
1919 if( markersProvider->GetCount() > 0 || ratsnestProvider->GetCount() > 0
1920 || fpWarningsProvider->GetCount() > 0 )
1921 {
1923 }
1924 }
1925
1927}
1928
1929
1931{
1932 JOB_EXPORT_PCB_IPC2581* job = dynamic_cast<JOB_EXPORT_PCB_IPC2581*>( aJob );
1933
1934 if( job == nullptr )
1936
1937 BOARD* brd = getBoard( job->m_filename );
1938
1939 if( !brd )
1941
1942 aJob->SetTitleBlock( brd->GetTitleBlock() );
1943
1944 if( job->GetConfiguredOutputPath().IsEmpty() )
1945 {
1946 wxFileName fn = brd->GetFileName();
1947 fn.SetName( fn.GetName() );
1948 fn.SetExt( FILEEXT::Ipc2581FileExtension );
1949
1950 job->SetWorkingOutputPath( fn.GetName() );
1951 }
1952
1953 wxString outPath = job->GetFullOutputPath( brd->GetProject() );
1954
1955 if( !PATHS::EnsurePathExists( outPath, true ) )
1956 {
1957 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
1959 }
1960
1961 std::map<std::string, UTF8> props;
1962 props["units"] = job->m_units == JOB_EXPORT_PCB_IPC2581::IPC2581_UNITS::MILLIMETERS ? "mm"
1963 : "inch";
1964 props["sigfig"] = wxString::Format( "%d", job->m_precision );
1965 props["version"] = job->m_version == JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION::C ? "C" : "B";
1966 props["OEMRef"] = job->m_colInternalId;
1967 props["mpn"] = job->m_colMfgPn;
1968 props["mfg"] = job->m_colMfg;
1969 props["dist"] = job->m_colDist;
1970 props["distpn"] = job->m_colDistPn;
1971
1972 wxString tempFile = wxFileName::CreateTempFileName( wxS( "pcbnew_ipc" ) );
1973 try
1974 {
1976 pi->SetProgressReporter( m_progressReporter );
1977 pi->SaveBoard( tempFile, brd, &props );
1978 }
1979 catch( const IO_ERROR& ioe )
1980 {
1981 m_reporter->Report( wxString::Format( _( "Error generating IPC2581 file '%s'.\n%s" ),
1982 job->m_filename,
1983 ioe.What() ),
1985
1986 wxRemoveFile( tempFile );
1987
1989 }
1990
1991 if( job->m_compress )
1992 {
1993 wxFileName tempfn = outPath;
1994 tempfn.SetExt( FILEEXT::Ipc2581FileExtension );
1995 wxFileName zipfn = tempFile;
1996 zipfn.SetExt( "zip" );
1997
1998 wxFFileOutputStream fnout( zipfn.GetFullPath() );
1999 wxZipOutputStream zip( fnout );
2000 wxFFileInputStream fnin( tempFile );
2001
2002 zip.PutNextEntry( tempfn.GetFullName() );
2003 fnin.Read( zip );
2004 zip.Close();
2005 fnout.Close();
2006
2007 wxRemoveFile( tempFile );
2008 tempFile = zipfn.GetFullPath();
2009 }
2010
2011 // If save succeeded, replace the original with what we just wrote
2012 if( !wxRenameFile( tempFile, outPath ) )
2013 {
2014 m_reporter->Report( wxString::Format( _( "Error generating IPC2581 file '%s'.\n"
2015 "Failed to rename temporary file '%s." )
2016 + wxS( "\n" ),
2017 outPath, tempFile ),
2019 }
2020
2022}
2023
2024
2026{
2027 JOB_EXPORT_PCB_ODB* job = dynamic_cast<JOB_EXPORT_PCB_ODB*>( aJob );
2028
2029 if( job == nullptr )
2031
2032 BOARD* brd = getBoard( job->m_filename );
2033
2034 if( !brd )
2036
2037 aJob->SetTitleBlock( brd->GetTitleBlock() );
2038
2039 wxString path = job->GetConfiguredOutputPath();
2040
2041 if( job->GetConfiguredOutputPath().IsEmpty() )
2042 {
2044 {
2045 // just basic folder name
2046 job->SetWorkingOutputPath( "odb" );
2047 }
2048 else
2049 {
2050 wxFileName fn( brd->GetFileName() );
2051 fn.SetName( fn.GetName() + wxS( "-odb" ) );
2052
2053 switch( job->m_compressionMode )
2054 {
2056 fn.SetExt( FILEEXT::ArchiveFileExtension );
2057 break;
2059 fn.SetExt( "tgz" );
2060 break;
2061 default: break;
2062 };
2063
2064 job->SetWorkingOutputPath( fn.GetFullName() );
2065 }
2066 }
2067
2069
2071}
2072
2073
2075{
2077 &aBrd->GetPageSettings(),
2078 aBrd->GetProject(),
2079 &aBrd->GetTitleBlock(),
2080 &aBrd->GetProperties() );
2081
2082 drawingSheet->SetSheetName( std::string() );
2083 drawingSheet->SetSheetPath( std::string() );
2084 drawingSheet->SetIsFirstPage( true );
2085
2086 drawingSheet->SetFileName( TO_UTF8( aBrd->GetFileName() ) );
2087
2088 return drawingSheet;
2089}
2090
2091
2092void PCBNEW_JOBS_HANDLER::loadOverrideDrawingSheet( BOARD* aBrd, const wxString& aSheetPath )
2093{
2094 // dont bother attempting to load a empty path, if there was one
2095 if( aSheetPath.IsEmpty() )
2096 return;
2097
2098 auto loadSheet =
2099 [&]( const wxString& path ) -> bool
2100 {
2103 resolver.SetProject( aBrd->GetProject() );
2105
2107 aBrd->GetProject()->GetProjectPath(),
2108 aBrd->GetEmbeddedFiles() );
2109 wxString msg;
2110
2111 if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename, &msg ) )
2112 {
2113 m_reporter->Report( wxString::Format( _( "Error loading drawing sheet '%s'." ),
2114 path )
2115 + wxS( "\n" ) + msg + wxS( "\n" ),
2117 return false;
2118 }
2119
2120 return true;
2121 };
2122
2123 if( loadSheet( aSheetPath ) )
2124 return;
2125
2126 // failed loading custom path, revert back to default
2127 loadSheet( aBrd->GetProject()->GetProjectFile().m_BoardDrawingSheetFile );
2128}
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
Execute the changes.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
const VECTOR2I & GetAuxOrigin()
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:295
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:817
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition: board.cpp:2589
const PAGE_INFO & GetPageSettings() const
Definition: board.h:697
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: board.cpp:327
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:703
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1713
const std::map< wxString, wxString > & GetProperties() const
Definition: board.h:367
const wxString & GetFileName() const
Definition: board.h:332
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:700
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:613
PROJECT * GetProject() const
Definition: board.h:499
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:934
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition: board.cpp:2085
void DeleteMARKERs()
Delete all MARKERS from the board.
Definition: board.cpp:1400
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:686
bool Zoom_T1(float aFactor)
Definition: camera.cpp:629
bool SetCurWindowSize(const wxSize &aSize)
Update the windows size of the camera.
Definition: camera.cpp:571
bool ViewCommand_T1(VIEW3D_TYPE aRequestedView)
Definition: camera.cpp:110
void RotateX_T1(float aAngleInRadians)
Definition: camera.cpp:680
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:692
bool ParametersChanged()
Definition: camera.cpp:730
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition: commit.h:80
static void GenerateODBPPFiles(const JOB_EXPORT_PCB_ODB &aJob, BOARD *aBoard, PCB_EDIT_FRAME *aParentFrame=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, REPORTER *aErrorReporter=nullptr)
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
int ShowModal() override
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)
Populate the list with a custom layout or the default layout if no custom layout is available.
static DS_DATA_MODEL & GetTheInstance()
Return 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.
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)
Determine the full path of the given file name.
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2451
void SetLink(const KIID &aLink)
Definition: footprint.h:875
void SetOrientation(const EDA_ANGLE &aNewAngle)
Definition: footprint.cpp:2539
EDA_ITEM * Clone() const override
Invoke a function on all children.
Definition: footprint.cpp:2129
std::deque< PAD * > & Pads()
Definition: footprint.h:204
const LIB_ID & GetFPID() const
Definition: footprint.h:246
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.
ODB_COMPRESSION m_compressionMode
@ ALL_LAYERS_ONE_FILE
DEPRECATED MODE.
@ ONE_PAGE_PER_LAYER_ONE_FILE
The most traditional output mode KiCad has had.
LSEQ m_printMaskLayer
Layers to include on all individual layer prints.
wxString m_libraryPath
wxString m_outputLibraryPath
bool m_parity
Definition: job_pcb_drc.h:33
bool m_reportAllTrackErrors
Definition: job_pcb_drc.h:32
VECTOR3D m_lightBottomIntensity
VECTOR3D m_lightTopIntensity
BG_STYLE m_bgStyle
VECTOR3D m_lightCameraIntensity
VECTOR3D m_rotation
wxString m_filename
VECTOR3D m_pivot
VECTOR3D m_lightSideIntensity
std::string m_colorPreset
bool m_exitCodeViolations
Definition: job_rc.h:54
int m_severity
Definition: job_rc.h:44
UNITS m_units
Definition: job_rc.h:42
OUTPUT_FORMAT m_format
Definition: job_rc.h:52
wxString m_filename
Definition: job_rc.h:33
An simple container class that lets us dispatch output jobs to kifaces.
Definition: job.h:182
void AddOutput(wxString aOutputPath)
Definition: job.h:209
wxString GetFullOutputPath(PROJECT *aProject) const
Returns the full output path for the job, taking into account the configured output path,...
Definition: job.cpp:100
wxString GetConfiguredOutputPath() const
Returns the configured output path for the job.
Definition: job.h:226
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: job.h:197
void SetWorkingOutputPath(const wxString &aPath)
Sets a transient output path for the job, it takes priority over the configured output path when GetF...
Definition: job.h:232
const std::map< wxString, wxString > & GetVarOverrides() const
Definition: job.h:190
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:285
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 void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr)
Send aPayload to aDestination from aSource.
Definition: kiway.cpp:527
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:49
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
LSEQ UIOrder() const
Return the copper, technical and user layers in the order shown in layer widget.
Definition: lset.cpp:688
LSEQ SeqStackupForPlotting() const
Return the sequence that is typical for a bottom-to-top stack-up.
Definition: lset.cpp:386
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:573
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:562
@ MARKER_DRAWING_SHEET
Definition: marker_base.h:56
Definition: pad.h:54
static bool EnsurePathExists(const wxString &aPath, bool aPathToFile=false)
Attempts to create a given path if it does not exist.
Definition: paths.cpp:467
void populateGerberPlotOptionsFromJob(PCB_PLOT_PARAMS &aPlotOpts, JOB_EXPORT_PCB_GERBER *aJob)
int JobExportFpUpgrade(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)
BOARD * getBoard(const wxString &aPath=wxEmptyString)
int JobExportRender(JOB *aJob)
int doFpExportSvg(JOB_FP_EXPORT_SVG *aSvgJob, const FOOTPRINT *aFootprint)
BOARD * GetBoard() const
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
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)
Definition: pcb_plotter.cpp:49
static void PlotJobToPlotOpts(PCB_PLOT_PARAMS &aOpts, JOB_EXPORT_PCB_PLOT *aJob)
Translate a JOB to PCB_PLOT_PARAMS.
Parameters and options when plotting/printing a board.
void SetDrillMarksType(DRILL_MARKS aVal)
void SetLayerSelection(LSET aSelection)
void SetPlotReference(bool aFlag)
void SetUseGerberX2format(bool aUse)
void SetPlotFrameRef(bool aFlag)
LSET GetLayerSelection() const
void SetPlotOnAllLayersSelection(LSET aSelection)
LSET GetPlotOnAllLayersSelection() const
void SetDisableGerberMacros(bool aDisable)
void SetGerberPrecision(int aPrecision)
void SetSubtractMaskFromSilk(bool aSubtract)
void SetPlotValue(bool aFlag)
void SetUseGerberProtelExtensions(bool aUse)
void SetIncludeGerberNetlistInfo(bool aUse)
bool m_PDFSingle
Generate a single PDF file for all layers.
void SetUseAuxOrigin(bool aAux)
bool GetUseGerberProtelExtensions() const
void SetFormat(PLOT_FORMAT aFormat)
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:125
Used to create Gerber drill files.
const wxString GetPlaceFileName(const wxString &aFullBaseFilename, PCB_LAYER_ID aLayer) const
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:
static wxString DecorateFilename(const wxString &aBaseName, bool aFront, bool aBack)
std::string GenPositionData()
build a string filled with the position data
wxString m_BoardDrawingSheetFile
PcbNew params.
Definition: project_file.h:164
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
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:140
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:146
virtual void ApplyTextVars(const std::map< wxString, wxString > &aVarsMap)
Applies the given var map, it will create or update existing vars.
Definition: project.cpp:101
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(const wxString &aFilename)
Return a handle to the a given settings by type.
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:64
T z
Definition: vector3.h:65
T x
Definition: vector3.h:63
wxString GetDefaultPlotExtension(PLOT_FORMAT aFormat)
Return the default plot extension for a format.
static DRILL_PRECISION precisionListForInches(2, 4)
static DRILL_PRECISION precisionListForMetric(3, 3)
std::function< void(PCB_MARKER *aMarker)> DRC_CUSTOM_MARKER_HANDLER
Definition: drc_engine.h:69
#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
@ FRAME_SCH
Definition: frame_type.h:34
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 BrepFileExtension
static const std::string JpegFileExtension
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 PngFileExtension
static const std::string FootprintPlaceFileExtension
static const std::string JsonFileExtension
static const std::string CsvFileExtension
static const std::string Ipc2581FileExtension
static const std::string GencadFileExtension
static const std::string StlFileExtension
static const std::string PlyFileExtension
static const std::string StepFileExtension
static const std::string SVGFileExtension
static const std::string VrmlFileExtension
static const std::string ArchiveFileExtension
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
KIID niluuid(0)
@ LAYER_3D_BACKGROUND_TOP
Definition: layer_ids.h:503
@ LAYER_3D_BACKGROUND_BOTTOM
Definition: layer_ids.h:502
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.
@ MAIL_SCH_GET_NETLIST
Definition: mail_type.h:49
static const int ERR_ARGS
Definition: exit_codes.h:31
static const int OK
Definition: exit_codes.h:30
static const int ERR_RC_VIOLATIONS
Rules check violation count was greater than 0.
Definition: exit_codes.h:37
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
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)
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:379
PLOTTER * StartPlotBoard(BOARD *aBoard, const PCB_PLOT_PARAMS *aPlotOpts, int aLayer, const wxString &aLayerName, const wxString &aFullFileName, const wxString &aSheetName, const wxString &aSheetPath, const wxString &aPageName=wxT("1"), const wxString &aPageNumber=wxEmptyString, const int aPageCount=1)
Open a new plotfile using the options (and especially the format) specified in the options and prepar...
void PlotBoardLayers(BOARD *aBoard, PLOTTER *aPlotter, const LSEQ &aLayerSequence, const PCB_PLOT_PARAMS &aPlotOptions)
Plot a sequence of board layer IDs.
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1073
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
std::vector< FAB_LAYER_COLOR > dummy
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:398
std::vector< KIGFX::COLOR4D > raytrace_lightColor
constexpr double IUTomm(int iu) const
Definition: base_units.h:86
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
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:695
Definition of file extensions used in Kicad.
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44