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, *m_reporter );
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
764 if( !plotter.Plot( outPath, aSvgJob->m_printMaskLayer,
767 layerName,
768 sheetName,
769 sheetPath ) )
770 {
772 }
773
774 return CLI::EXIT_CODES::OK;
775}
776
777
779{
780 JOB_EXPORT_PCB_DXF* aDxfJob = dynamic_cast<JOB_EXPORT_PCB_DXF*>( aJob );
781
782 if( aDxfJob == nullptr )
784
785 BOARD* brd = getBoard( aDxfJob->m_filename );
786
787 if( !brd )
789
790 aJob->SetTitleBlock( brd->GetTitleBlock() );
792 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
794
795
797 {
798 if( aDxfJob->GetConfiguredOutputPath().IsEmpty() )
799 {
800 wxFileName fn = brd->GetFileName();
801 fn.SetName( fn.GetName() );
802 fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::DXF ) );
803
804 aDxfJob->SetWorkingOutputPath( fn.GetFullName() );
805 }
806 }
807
808 wxString outPath = aDxfJob->GetFullOutputPath( brd->GetProject() );
809
811 {
812 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
814 }
815
816 PCB_PLOT_PARAMS plotOpts;
817 PCB_PLOTTER::PlotJobToPlotOpts( plotOpts, aDxfJob, *m_reporter);
818
819 PCB_PLOTTER plotter( brd, m_reporter, plotOpts );
820
821 std::optional<wxString> layerName;
822 std::optional<wxString> sheetName;
823 std::optional<wxString> sheetPath;
824
826 {
827 if( aJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
828 layerName = aDxfJob->GetVarOverrides().at( wxT( "LAYER" ) );
829
830 if( aJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
831 sheetName = aDxfJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
832
833 if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
834 sheetPath = aDxfJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
835 }
836
837 if( !plotter.Plot( outPath, aDxfJob->m_printMaskLayer,
839 aDxfJob->m_genMode == JOB_EXPORT_PCB_DXF::GEN_MODE::SINGLE, layerName,
840 sheetName, sheetPath ) )
841 {
843 }
844
845 return CLI::EXIT_CODES::OK;
846}
847
848
850{
851 JOB_EXPORT_PCB_PDF* aPdfJob = dynamic_cast<JOB_EXPORT_PCB_PDF*>( aJob );
852
853 if( aPdfJob == nullptr )
855
856 BOARD* brd = getBoard( aPdfJob->m_filename );
857
858 if( !brd )
860
861 aJob->SetTitleBlock( brd->GetTitleBlock() );
863 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
865
867 && aPdfJob->GetConfiguredOutputPath().IsEmpty() )
868 {
869 wxFileName fn = brd->GetFileName();
870 fn.SetName( fn.GetName() );
871 fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::PDF ) );
872
873 aPdfJob->SetWorkingOutputPath( fn.GetFullName() );
874 }
875
876 PCB_PLOT_PARAMS plotOpts;
877 PCB_PLOTTER::PlotJobToPlotOpts( plotOpts, aPdfJob, *m_reporter );
878
879 int returnCode = CLI::EXIT_CODES::OK;
880
881 // ensure this is set for this one gen mode
883 {
884 plotOpts.m_PDFSingle = true;
885 }
886
887 PCB_PLOTTER pcbPlotter( brd, m_reporter, plotOpts );
888
889 wxString outPath = aPdfJob->GetFullOutputPath( brd->GetProject() );
890
892 {
893 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
895 }
896
897 std::optional<wxString> layerName;
898 std::optional<wxString> sheetName;
899 std::optional<wxString> sheetPath;
901 {
902 if( aPdfJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
903 layerName = aPdfJob->GetVarOverrides().at( wxT( "LAYER" ) );
904
905 if( aPdfJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
906 sheetName = aPdfJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
907
908 if( aPdfJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
909 sheetPath = aPdfJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
910 }
911
912
914 if( !pcbPlotter.Plot( outPath, aPdfJob->m_printMaskLayer,
916 false,
918 layerName,
919 sheetName,
920 sheetPath ) )
921 {
922 returnCode = CLI::EXIT_CODES::ERR_UNKNOWN;
923 }
924
925 return returnCode;
926}
927
928
930{
931 int exitCode = CLI::EXIT_CODES::OK;
932 JOB_EXPORT_PCB_GERBERS* aGerberJob = dynamic_cast<JOB_EXPORT_PCB_GERBERS*>( aJob );
933
934 if( aGerberJob == nullptr )
936
937 BOARD* brd = getBoard( aGerberJob->m_filename );
938
939 if( !brd )
941
942 wxString outPath = aGerberJob->GetFullOutputPath( brd->GetProject() );
943
944 if( !PATHS::EnsurePathExists( outPath, false ) )
945 {
946 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
948 }
949
950 aJob->SetTitleBlock( brd->GetTitleBlock() );
951 loadOverrideDrawingSheet( brd, aGerberJob->m_drawingSheet );
952 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
954
955 PCB_PLOT_PARAMS boardPlotOptions = brd->GetPlotOptions();
956 LSET plotOnAllLayersSelection = boardPlotOptions.GetPlotOnAllLayersSelection();
957 GERBER_JOBFILE_WRITER jobfile_writer( brd );
958
959 wxString fileExt;
960
961 if( aGerberJob->m_useBoardPlotParams )
962 {
963 // The board plot options are saved with all copper layers enabled, even those that don't
964 // exist in the current stackup. This is done so the layers are automatically enabled in the plot
965 // dialog when the user enables them. We need to filter out these not-enabled layers here so
966 // we don't plot 32 layers when we only have 4, etc.
967 LSET plotLayers = ( boardPlotOptions.GetLayerSelection() & LSET::AllNonCuMask() )
968 | ( brd->GetEnabledLayers() & LSET::AllCuMask() );
969 aGerberJob->m_printMaskLayer = plotLayers.SeqStackupForPlotting();
970 aGerberJob->m_layersIncludeOnAll = boardPlotOptions.GetPlotOnAllLayersSelection().UIOrder();
971 }
972 else
973 {
974 // default to the board enabled layers
975 if( aGerberJob->m_printMaskLayer.empty() )
977
978 if( aGerberJob->m_layersIncludeOnAllSet )
979 aGerberJob->m_layersIncludeOnAll = plotOnAllLayersSelection.UIOrder();
980 }
981
982 // Ensure layers to plot are restricted to enabled layers of the board to plot
983 LSET layersToPlot = LSET( { aGerberJob->m_printMaskLayer } ) & brd->GetEnabledLayers();
984
985 for( PCB_LAYER_ID layer : layersToPlot.UIOrder() )
986 {
987 LSEQ plotSequence;
988
989 // Base layer always gets plotted first.
990 plotSequence.push_back( layer );
991
992 // Now all the "include on all" layers
993 for( PCB_LAYER_ID layer_all : aGerberJob->m_layersIncludeOnAll )
994 {
995 // Don't plot the same layer more than once;
996 if( find( plotSequence.begin(), plotSequence.end(), layer_all ) != plotSequence.end() )
997 continue;
998
999 plotSequence.push_back( layer_all );
1000 }
1001
1002 // Pick the basename from the board file
1003 wxFileName fn( brd->GetFileName() );
1004 wxString layerName = brd->GetLayerName( layer );
1005 wxString sheetName;
1006 wxString sheetPath;
1007 PCB_PLOT_PARAMS plotOpts;
1008
1009 if( aGerberJob->m_useBoardPlotParams )
1010 plotOpts = boardPlotOptions;
1011 else
1012 populateGerberPlotOptionsFromJob( plotOpts, aGerberJob );
1013
1014 if( plotOpts.GetUseGerberProtelExtensions() )
1015 fileExt = GetGerberProtelExtension( layer );
1016 else
1018
1019 BuildPlotFileName( &fn, outPath, layerName, fileExt );
1020 wxString fullname = fn.GetFullName();
1021
1022 jobfile_writer.AddGbrFile( layer, fullname );
1023
1024 if( aJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
1025 layerName = aJob->GetVarOverrides().at( wxT( "LAYER" ) );
1026
1027 if( aJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
1028 sheetName = aJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
1029
1030 if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
1031 sheetPath = aJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
1032
1033 // We are feeding it one layer at the start here to silence a logic check
1034 GERBER_PLOTTER* plotter;
1035 {
1037 plotter = (GERBER_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer, layerName,
1038 fn.GetFullPath(), sheetName, sheetPath );
1039 }
1040
1041 if( plotter )
1042 {
1043 m_reporter->Report( wxString::Format( _( "Plotted to '%s'.\n" ), fn.GetFullPath() ),
1046 PlotBoardLayers( brd, plotter, plotSequence, plotOpts );
1047 plotter->EndPlot();
1048 }
1049 else
1050 {
1051 m_reporter->Report( wxString::Format( _( "Failed to plot to '%s'.\n" ),
1052 fn.GetFullPath() ),
1055 }
1056
1057 delete plotter;
1058 }
1059
1060 wxFileName fn( brd->GetFileName() );
1061
1062 // Build gerber job file from basename
1063 BuildPlotFileName( &fn, outPath, wxT( "job" ), FILEEXT::GerberJobFileExtension );
1064 jobfile_writer.CreateJobFile( fn.GetFullPath() );
1065
1066 return exitCode;
1067}
1068
1070{
1071 JOB_EXPORT_PCB_GENCAD* aGencadJob = dynamic_cast<JOB_EXPORT_PCB_GENCAD*>( aJob );
1072
1073 if( aGencadJob == nullptr )
1075
1076 BOARD* brd = LoadBoard( aGencadJob->m_filename, true ); // Ensure m_board is of type BOARD*
1077
1078 if( brd == nullptr )
1080
1081 GENCAD_EXPORTER exporter( brd );
1082
1083 VECTOR2I GencadOffset;
1084 VECTOR2I auxOrigin = brd->GetDesignSettings().GetAuxOrigin();
1085 GencadOffset.x = aGencadJob->m_useDrillOrigin ? auxOrigin.x : 0;
1086 GencadOffset.y = aGencadJob->m_useDrillOrigin ? auxOrigin.y : 0;
1087
1088 exporter.FlipBottomPads( aGencadJob->m_flipBottomPads );
1089 exporter.UsePinNamesUnique( aGencadJob->m_useUniquePins );
1090 exporter.UseIndividualShapes( aGencadJob->m_useIndividualShapes );
1091 exporter.SetPlotOffet( GencadOffset );
1092 exporter.StoreOriginCoordsInFile( aGencadJob->m_storeOriginCoords );
1093
1094 if( aGencadJob->GetConfiguredOutputPath().IsEmpty() )
1095 {
1096 wxFileName fn = brd->GetFileName();
1097 fn.SetName( fn.GetName() );
1098 fn.SetExt( FILEEXT::GencadFileExtension );
1099
1100 aGencadJob->SetWorkingOutputPath( fn.GetFullName() );
1101 }
1102
1103 wxString outPath = aGencadJob->GetFullOutputPath( brd->GetProject() );
1104
1105 if( !PATHS::EnsurePathExists( outPath, true ) )
1106 {
1107 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
1109 }
1110
1111 if( !exporter.WriteFile( outPath ) )
1112 {
1113 m_reporter->Report( wxString::Format( _( "Failed to create file '%s'.\n" ), outPath ),
1115
1117 }
1118
1119 m_reporter->Report( _( "Successfully created genCAD file\n" ), RPT_SEVERITY_INFO );
1120
1121 return CLI::EXIT_CODES::OK;
1122}
1123
1124
1126 JOB_EXPORT_PCB_GERBER* aJob )
1127{
1128 aPlotOpts.SetFormat( PLOT_FORMAT::GERBER );
1129
1130 aPlotOpts.SetPlotFrameRef( aJob->m_plotDrawingSheet );
1131 aPlotOpts.SetPlotValue( aJob->m_plotFootprintValues );
1132 aPlotOpts.SetPlotReference( aJob->m_plotRefDes );
1133
1135
1136 // Always disable plot pad holes
1137 aPlotOpts.SetDrillMarksType( DRILL_MARKS::NO_DRILL_SHAPE );
1138
1140 aPlotOpts.SetUseGerberX2format( aJob->m_useX2Format );
1142 aPlotOpts.SetUseAuxOrigin( aJob->m_useDrillOrigin );
1144 aPlotOpts.SetGerberPrecision( aJob->m_precision );
1145}
1146
1147
1149{
1150 int exitCode = CLI::EXIT_CODES::OK;
1151 JOB_EXPORT_PCB_GERBER* aGerberJob = dynamic_cast<JOB_EXPORT_PCB_GERBER*>( aJob );
1152
1153 if( aGerberJob == nullptr )
1155
1156 BOARD* brd = getBoard( aGerberJob->m_filename );
1157
1158 if( !brd )
1160
1161 aJob->SetTitleBlock( brd->GetTitleBlock() );
1162 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
1163 brd->SynchronizeProperties();
1164
1165 if( aGerberJob->GetConfiguredOutputPath().IsEmpty() )
1166 {
1167 wxFileName fn = brd->GetFileName();
1168 fn.SetName( fn.GetName() );
1169 fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::GERBER ) );
1170
1171 aGerberJob->SetWorkingOutputPath( fn.GetFullName() );
1172 }
1173
1174 PCB_PLOT_PARAMS plotOpts;
1175 populateGerberPlotOptionsFromJob( plotOpts, aGerberJob );
1176 plotOpts.SetLayerSelection( aGerberJob->m_printMaskLayer );
1178
1180 wxString layerName;
1181 wxString sheetName;
1182 wxString sheetPath;
1183
1184 // The first layer will be treated as the layer name for the gerber header,
1185 // the other layers will be treated equivalent to the "Plot on All Layers" option
1186 // in the GUI
1187 if( aGerberJob->m_printMaskLayer.size() >= 1 )
1188 {
1189 layer = aGerberJob->m_printMaskLayer.front();
1190 layerName = brd->GetLayerName( layer );
1191 }
1192
1193 if( aJob->GetVarOverrides().contains( wxT( "LAYER" ) ) )
1194 layerName = aJob->GetVarOverrides().at( wxT( "LAYER" ) );
1195
1196 if( aJob->GetVarOverrides().contains( wxT( "SHEETNAME" ) ) )
1197 sheetName = aJob->GetVarOverrides().at( wxT( "SHEETNAME" ) );
1198
1199 if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
1200 sheetPath = aJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
1201
1202 // We are feeding it one layer at the start here to silence a logic check
1203 GERBER_PLOTTER* plotter = (GERBER_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer, layerName,
1204 aGerberJob->GetFullOutputPath( brd->GetProject() ),
1205 sheetName, sheetPath );
1206
1207 if( plotter )
1208 {
1209 PlotBoardLayers( brd, plotter, aGerberJob->m_printMaskLayer, plotOpts );
1210 plotter->EndPlot();
1211 }
1212 else
1213 {
1214 m_reporter->Report( wxString::Format( _( "Failed to plot to '%s'.\n" ),
1215 aGerberJob->GetFullOutputPath( brd->GetProject() ) ),
1218 }
1219
1220 delete plotter;
1221
1222 return exitCode;
1223}
1224
1227
1228
1230{
1231 JOB_EXPORT_PCB_DRILL* aDrillJob = dynamic_cast<JOB_EXPORT_PCB_DRILL*>( aJob );
1232
1233 if( aDrillJob == nullptr )
1235
1236 BOARD* brd = getBoard( aDrillJob->m_filename );
1237
1238 if( !brd )
1240
1241 aJob->SetTitleBlock( brd->GetTitleBlock() );
1242
1243 wxString outPath = aDrillJob->GetFullOutputPath( brd->GetProject() );
1244
1245 if( !PATHS::EnsurePathExists( outPath ) )
1246 {
1247 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
1249 }
1250
1251 std::unique_ptr<GENDRILL_WRITER_BASE> drillWriter;
1252
1254 drillWriter = std::make_unique<EXCELLON_WRITER>( brd );
1255 else
1256 drillWriter = std::make_unique<GERBER_WRITER>( brd );
1257
1258 VECTOR2I offset;
1259
1261 offset = VECTOR2I( 0, 0 );
1262 else
1263 offset = brd->GetDesignSettings().GetAuxOrigin();
1264
1265 PLOT_FORMAT mapFormat = PLOT_FORMAT::PDF;
1266
1267 switch( aDrillJob->m_mapFormat )
1268 {
1269 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::POSTSCRIPT: mapFormat = PLOT_FORMAT::POST; break;
1270 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::GERBER_X2: mapFormat = PLOT_FORMAT::GERBER; break;
1271 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::DXF: mapFormat = PLOT_FORMAT::DXF; break;
1272 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::SVG: mapFormat = PLOT_FORMAT::SVG; break;
1273 default:
1274 case JOB_EXPORT_PCB_DRILL::MAP_FORMAT::PDF: mapFormat = PLOT_FORMAT::PDF; break;
1275 }
1276
1278 {
1280 switch( aDrillJob->m_zeroFormat )
1281 {
1284 break;
1287 break;
1290 break;
1292 default:
1294 break;
1295 }
1296
1297 DRILL_PRECISION precision;
1298
1300 precision = precisionListForInches;
1301 else
1302 precision = precisionListForMetric;
1303
1304 EXCELLON_WRITER* excellonWriter = dynamic_cast<EXCELLON_WRITER*>( drillWriter.get() );
1305
1306 if( excellonWriter == nullptr )
1308
1309 excellonWriter->SetFormat( aDrillJob->m_drillUnits
1311 zeroFmt, precision.m_Lhs, precision.m_Rhs );
1312 excellonWriter->SetOptions( aDrillJob->m_excellonMirrorY,
1313 aDrillJob->m_excellonMinimalHeader,
1314 offset, aDrillJob->m_excellonCombinePTHNPTH );
1315 excellonWriter->SetRouteModeForOvalHoles( aDrillJob->m_excellonOvalDrillRoute );
1316 excellonWriter->SetMapFileFormat( mapFormat );
1317
1318 if( !excellonWriter->CreateDrillandMapFilesSet( outPath, true, aDrillJob->m_generateMap,
1319 m_reporter ) )
1320 {
1322 }
1323 }
1325 {
1326 GERBER_WRITER* gerberWriter = dynamic_cast<GERBER_WRITER*>( drillWriter.get() );
1327
1328 if( gerberWriter == nullptr )
1330
1331 // Set gerber precision: only 5 or 6 digits for mantissa are allowed
1332 // (SetFormat() accept 5 or 6, and any other value set the precision to 5)
1333 // the integer part precision is always 4, and units always mm
1334 gerberWriter->SetFormat( aDrillJob->m_gerberPrecision );
1335 gerberWriter->SetOptions( offset );
1336 gerberWriter->SetMapFileFormat( mapFormat );
1337
1338 if( !gerberWriter->CreateDrillandMapFilesSet( outPath, true, aDrillJob->m_generateMap,
1339 m_reporter ) )
1340 {
1342 }
1343 }
1344
1345 return CLI::EXIT_CODES::OK;
1346}
1347
1348
1350{
1351 JOB_EXPORT_PCB_POS* aPosJob = dynamic_cast<JOB_EXPORT_PCB_POS*>( aJob );
1352
1353 if( aPosJob == nullptr )
1355
1356 BOARD* brd = getBoard( aPosJob->m_filename );
1357
1358 if( !brd )
1360
1361 aJob->SetTitleBlock( brd->GetTitleBlock() );
1362
1363 if( aPosJob->GetConfiguredOutputPath().IsEmpty() )
1364 {
1365 wxFileName fn = brd->GetFileName();
1366 fn.SetName( fn.GetName() );
1367
1370 else if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV )
1371 fn.SetExt( FILEEXT::CsvFileExtension );
1372 else if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::GERBER )
1373 fn.SetExt( FILEEXT::GerberFileExtension );
1374
1375 aPosJob->SetWorkingOutputPath( fn.GetFullName() );
1376 }
1377
1378 wxString outPath = aPosJob->GetFullOutputPath( brd->GetProject() );
1379
1380 if( !PATHS::EnsurePathExists( outPath, true ) )
1381 {
1382 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
1384 }
1385
1388 {
1389 wxFileName fn( outPath );
1390 wxString baseName = fn.GetName();
1391
1392 auto exportPlaceFile =
1393 [&]( bool frontSide, bool backSide, const wxString& curr_outPath ) -> bool
1394 {
1395 FILE* file = wxFopen( curr_outPath, wxS( "wt" ) );
1396 wxCHECK( file, false );
1397
1398 PLACE_FILE_EXPORTER exporter( brd,
1400 aPosJob->m_smdOnly,
1402 aPosJob->m_excludeDNP,
1403 frontSide,
1404 backSide,
1407 aPosJob->m_negateBottomX );
1408
1409 std::string data = exporter.GenPositionData();
1410 fputs( data.c_str(), file );
1411 fclose( file );
1412
1413 return true;
1414 };
1415
1416 if( aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH && !aPosJob->m_singleFile )
1417 {
1418 fn.SetName( PLACE_FILE_EXPORTER::DecorateFilename( baseName, true, false ) );
1419
1420 if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV && !aPosJob->m_nakedFilename )
1421 fn.SetName( fn.GetName() + wxT( "-" ) + FILEEXT::FootprintPlaceFileExtension );
1422
1423 if( exportPlaceFile( true, false, fn.GetFullPath() ) )
1424 {
1425 m_reporter->Report( wxString::Format( _( "Wrote front position data to '%s'.\n" ),
1426 fn.GetFullPath() ),
1428
1429 aPosJob->AddOutput( fn.GetFullPath() );
1430 }
1431 else
1432 {
1434 }
1435
1436 fn.SetName( PLACE_FILE_EXPORTER::DecorateFilename( baseName, false, true ) );
1437
1438 if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV && !aPosJob->m_nakedFilename )
1439 fn.SetName( fn.GetName() + wxT( "-" ) + FILEEXT::FootprintPlaceFileExtension );
1440
1441 if( exportPlaceFile( false, true, fn.GetFullPath() ) )
1442 {
1443 m_reporter->Report( wxString::Format( _( "Wrote back position data to '%s'.\n" ),
1444 fn.GetFullPath() ),
1446
1447 aPosJob->AddOutput( fn.GetFullPath() );
1448 }
1449 else
1450 {
1452 }
1453 }
1454 else
1455 {
1456 bool front = aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::FRONT
1458
1459 bool back = aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BACK
1461
1462 if( !aPosJob->m_nakedFilename )
1463 {
1464 fn.SetName( PLACE_FILE_EXPORTER::DecorateFilename( fn.GetName(), front, back ) );
1465
1467 fn.SetName( fn.GetName() + wxT( "-" ) + FILEEXT::FootprintPlaceFileExtension );
1468 }
1469
1470 if( exportPlaceFile( front, back, fn.GetFullPath() ) )
1471 {
1472 m_reporter->Report( wxString::Format( _( "Wrote position data to '%s'.\n" ),
1473 fn.GetFullPath() ),
1475
1476 aPosJob->AddOutput( fn.GetFullPath() );
1477 }
1478 else
1479 {
1481 }
1482 }
1483 }
1484 else if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::GERBER )
1485 {
1486 PLACEFILE_GERBER_WRITER exporter( brd );
1487 PCB_LAYER_ID gbrLayer = F_Cu;
1488 wxString outPath_base = outPath;
1489
1491 || aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH )
1492 {
1493 if( aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH || !aPosJob->m_nakedFilename )
1494 outPath = exporter.GetPlaceFileName( outPath, gbrLayer );
1495
1496 if( exporter.CreatePlaceFile( outPath, gbrLayer, aPosJob->m_gerberBoardEdge ) >= 0 )
1497 {
1498 m_reporter->Report( wxString::Format( _( "Wrote front position data to '%s'.\n" ),
1499 outPath ),
1501
1502 aPosJob->AddOutput( outPath );
1503 }
1504 else
1505 {
1507 }
1508 }
1509
1511 || aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH )
1512 {
1513 gbrLayer = B_Cu;
1514
1515 outPath = outPath_base;
1516
1517 if( aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BOTH || !aPosJob->m_nakedFilename )
1518 outPath = exporter.GetPlaceFileName( outPath, gbrLayer );
1519
1520 if( exporter.CreatePlaceFile( outPath, gbrLayer, aPosJob->m_gerberBoardEdge ) >= 0 )
1521 {
1522 m_reporter->Report( wxString::Format( _( "Wrote back position data to '%s'.\n" ),
1523 outPath ),
1525
1526 aPosJob->AddOutput( outPath );
1527 }
1528 else
1529 {
1531 }
1532 }
1533 }
1534
1535 return CLI::EXIT_CODES::OK;
1536}
1537
1538extern FOOTPRINT* try_load_footprint( const wxFileName& aFileName, PCB_IO_MGR::PCB_FILE_T aFileType,
1539 const wxString& aName );
1540
1541
1543{
1544 JOB_FP_UPGRADE* upgradeJob = dynamic_cast<JOB_FP_UPGRADE*>( aJob );
1545
1546 if( upgradeJob == nullptr )
1548
1550
1551 if( !upgradeJob->m_outputLibraryPath.IsEmpty() )
1552 {
1553 if( wxFile::Exists( upgradeJob->m_outputLibraryPath )
1554 || wxDir::Exists( upgradeJob->m_outputLibraryPath) )
1555 {
1556 m_reporter->Report( _( "Output path must not conflict with existing path\n" ),
1559 }
1560 }
1561 else if( fileType != PCB_IO_MGR::KICAD_SEXP )
1562 {
1563 m_reporter->Report( _( "Output path must be specified to convert legacy and non-KiCad libraries\n" ),
1565
1567 }
1568
1570 {
1571 if( !wxDir::Exists( upgradeJob->m_libraryPath ) )
1572 {
1573 m_reporter->Report( _( "Footprint library path does not exist or is not accessible\n" ),
1576 }
1577
1579 FP_CACHE fpLib( &pcb_io, upgradeJob->m_libraryPath );
1580
1581 try
1582 {
1583 fpLib.Load();
1584 }
1585 catch( ... )
1586 {
1587 m_reporter->Report( _( "Unable to load library\n" ), RPT_SEVERITY_ERROR );
1589 }
1590
1591 bool shouldSave = upgradeJob->m_force;
1592
1593 for( const auto& footprint : fpLib.GetFootprints() )
1594 {
1595 if( footprint.second->GetFootprint()->GetFileFormatVersionAtLoad()
1597 {
1598 shouldSave = true;
1599 }
1600 }
1601
1602 if( shouldSave )
1603 {
1604 try
1605 {
1606 if( !upgradeJob->m_outputLibraryPath.IsEmpty() )
1607 fpLib.SetPath( upgradeJob->m_outputLibraryPath );
1608
1609 fpLib.Save();
1610 }
1611 catch( ... )
1612 {
1613 m_reporter->Report( _( "Unable to save library\n" ), RPT_SEVERITY_ERROR );
1615 }
1616 }
1617 else
1618 {
1619 m_reporter->Report( _( "Footprint library was not updated\n" ), RPT_SEVERITY_ERROR );
1620 }
1621 }
1622 else
1623 {
1624 if( !PCB_IO_MGR::ConvertLibrary( nullptr, upgradeJob->m_libraryPath,
1625 upgradeJob->m_outputLibraryPath, nullptr /* REPORTER */ ) )
1626 {
1627 m_reporter->Report( ( "Unable to convert library\n" ), RPT_SEVERITY_ERROR );
1629 }
1630 }
1631
1632 return CLI::EXIT_CODES::OK;
1633}
1634
1635
1637{
1638 JOB_FP_EXPORT_SVG* svgJob = dynamic_cast<JOB_FP_EXPORT_SVG*>( aJob );
1639
1640 if( svgJob == nullptr )
1642
1644 FP_CACHE fpLib( &pcb_io, svgJob->m_libraryPath );
1645
1646 try
1647 {
1648 fpLib.Load();
1649 }
1650 catch( ... )
1651 {
1652 m_reporter->Report( _( "Unable to load library\n" ), RPT_SEVERITY_ERROR );
1654 }
1655
1656 if( !svgJob->m_outputDirectory.IsEmpty() && !wxDir::Exists( svgJob->m_outputDirectory ) )
1657 {
1658 wxFileName::Mkdir( svgJob->m_outputDirectory );
1659 }
1660
1661 int exitCode = CLI::EXIT_CODES::OK;
1662
1663 // Just plot all the symbols we can
1664 boost::ptr_map<wxString, FP_CACHE_ENTRY>& footprintMap = fpLib.GetFootprints();
1665
1666 bool singleFpPlotted = false;
1667
1668 for( auto it = footprintMap.begin(); it != footprintMap.end(); ++it )
1669 {
1670 const std::unique_ptr<FOOTPRINT>& fp = it->second->GetFootprint();
1671
1672 if( !svgJob->m_footprint.IsEmpty() )
1673 {
1674 if( fp->GetFPID().GetLibItemName().wx_str() != svgJob->m_footprint )
1675 {
1676 // skip until we find the right footprint
1677 continue;
1678 }
1679 else
1680 {
1681 singleFpPlotted = true;
1682 }
1683 }
1684
1685 exitCode = doFpExportSvg( svgJob, fp.get() );
1686
1687 if( exitCode != CLI::EXIT_CODES::OK )
1688 break;
1689 }
1690
1691 if( !svgJob->m_footprint.IsEmpty() && !singleFpPlotted )
1692 {
1693 m_reporter->Report( _( "The given footprint could not be found to export." ) + wxS( "\n" ),
1695 }
1696
1697 return CLI::EXIT_CODES::OK;
1698}
1699
1700
1702{
1703 // the hack for now is we create fake boards containing the footprint and plot the board
1704 // until we refactor better plot api later
1705 std::unique_ptr<BOARD> brd;
1706 brd.reset( CreateEmptyBoard() );
1707 brd->GetProject()->ApplyTextVars( aSvgJob->GetVarOverrides() );
1708 brd->SynchronizeProperties();
1709
1710 FOOTPRINT* fp = dynamic_cast<FOOTPRINT*>( aFootprint->Clone() );
1711
1712 if( fp == nullptr )
1714
1715 fp->SetLink( niluuid );
1716 fp->SetFlags( IS_NEW );
1717 fp->SetParent( brd.get() );
1718
1719 for( PAD* pad : fp->Pads() )
1720 {
1721 pad->SetLocalRatsnestVisible( false );
1722 pad->SetNetCode( 0 );
1723 }
1724
1725 fp->SetOrientation( ANGLE_0 );
1726 fp->SetPosition( VECTOR2I( 0, 0 ) );
1727
1728 brd->Add( fp, ADD_MODE::INSERT, true );
1729
1730 wxFileName outputFile;
1731 outputFile.SetPath( aSvgJob->m_outputDirectory );
1732 outputFile.SetName( aFootprint->GetFPID().GetLibItemName().wx_str() );
1733 outputFile.SetExt( FILEEXT::SVGFileExtension );
1734
1735 m_reporter->Report( wxString::Format( _( "Plotting footprint '%s' to '%s'\n" ),
1736 aFootprint->GetFPID().GetLibItemName().wx_str(),
1737 outputFile.GetFullPath() ),
1739
1740
1741 PCB_PLOT_SVG_OPTIONS svgPlotOptions;
1742 svgPlotOptions.m_blackAndWhite = aSvgJob->m_blackAndWhite;
1743 svgPlotOptions.m_colorTheme = aSvgJob->m_colorTheme;
1744 svgPlotOptions.m_outputFile = outputFile.GetFullPath();
1745 svgPlotOptions.m_mirror = false;
1746 svgPlotOptions.m_pageSizeMode = 2; // board bounding box
1747 svgPlotOptions.m_printMaskLayer = aSvgJob->m_printMaskLayer;
1748 svgPlotOptions.m_sketchPadsOnFabLayers = aSvgJob->m_sketchPadsOnFabLayers;
1749 svgPlotOptions.m_hideDNPFPsOnFabLayers = aSvgJob->m_hideDNPFPsOnFabLayers;
1750 svgPlotOptions.m_sketchDNPFPsOnFabLayers = aSvgJob->m_sketchDNPFPsOnFabLayers;
1752 svgPlotOptions.m_plotFrame = false;
1753
1754 if( !EXPORT_SVG::Plot( brd.get(), svgPlotOptions ) )
1755 m_reporter->Report( _( "Error creating svg file" ) + wxS( "\n" ), RPT_SEVERITY_ERROR );
1756
1757 return CLI::EXIT_CODES::OK;
1758}
1759
1760
1762{
1763 JOB_PCB_DRC* drcJob = dynamic_cast<JOB_PCB_DRC*>( aJob );
1764
1765 if( drcJob == nullptr )
1767
1768 BOARD* brd = getBoard( drcJob->m_filename );
1769
1770 if( !brd )
1772
1773 aJob->SetTitleBlock( brd->GetTitleBlock() );
1774 brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
1775 brd->SynchronizeProperties();
1776
1777 if( drcJob->GetConfiguredOutputPath().IsEmpty() )
1778 {
1779 wxFileName fn = brd->GetFileName();
1780 fn.SetName( fn.GetName() + wxS( "-drc" ) );
1781
1783 fn.SetExt( FILEEXT::JsonFileExtension );
1784 else
1785 fn.SetExt( FILEEXT::ReportFileExtension );
1786
1787 drcJob->SetWorkingOutputPath( fn.GetFullName() );
1788 }
1789
1790 wxString outPath = drcJob->GetFullOutputPath( brd->GetProject() );
1791
1792 if( !PATHS::EnsurePathExists( outPath, true ) )
1793 {
1794 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
1796 }
1797
1798 EDA_UNITS units;
1799
1800 switch( drcJob->m_units )
1801 {
1802 case JOB_PCB_DRC::UNITS::INCHES: units = EDA_UNITS::INCHES; break;
1803 case JOB_PCB_DRC::UNITS::MILS: units = EDA_UNITS::MILS; break;
1804 case JOB_PCB_DRC::UNITS::MILLIMETERS: units = EDA_UNITS::MILLIMETRES; break;
1805 default: units = EDA_UNITS::MILLIMETRES; break;
1806 }
1807
1808 std::shared_ptr<DRC_ENGINE> drcEngine = brd->GetDesignSettings().m_DRCEngine;
1809 std::unique_ptr<NETLIST> netlist = std::make_unique<NETLIST>();
1810
1811 drcEngine->SetDrawingSheet( getDrawingSheetProxyView( brd ) );
1812
1813 // BOARD_COMMIT uses TOOL_MANAGER to grab the board internally so we must give it one
1814 TOOL_MANAGER* toolManager = new TOOL_MANAGER;
1815 toolManager->SetEnvironment( brd, nullptr, nullptr, Kiface().KifaceSettings(), nullptr );
1816
1817 BOARD_COMMIT commit( toolManager );
1818 bool checkParity = drcJob->m_parity;
1819 std::string netlist_str;
1820
1821 if( checkParity )
1822 {
1823 wxString annotateMsg = _( "Schematic parity tests require a fully annotated schematic." );
1824 netlist_str = annotateMsg;
1825
1826 // The KIFACE_NETLIST_SCHEMATIC function has some broken-ness that the schematic
1827 // frame's version does not, but it is the only one that works in CLI, so we use it
1828 // if we don't have the sch frame open.
1829 // TODO: clean this up, see https://gitlab.com/kicad/code/kicad/-/issues/19929
1830 if( m_kiway->Player( FRAME_SCH, false ) )
1831 {
1833 }
1834 else
1835 {
1836 wxFileName schematicPath( drcJob->m_filename );
1837 schematicPath.SetExt( FILEEXT::KiCadSchematicFileExtension );
1838
1839 if( !schematicPath.Exists() )
1840 schematicPath.SetExt( FILEEXT::LegacySchematicFileExtension );
1841
1842 if( !schematicPath.Exists() )
1843 {
1844 m_reporter->Report( _( "Failed to fetch schematic netlist for parity tests.\n" ),
1846 checkParity = false;
1847 }
1848 else
1849 {
1850 typedef bool ( *NETLIST_FN_PTR )( const wxString&, std::string& );
1852 NETLIST_FN_PTR netlister =
1853 (NETLIST_FN_PTR) eeschema->IfaceOrAddress( KIFACE_NETLIST_SCHEMATIC );
1854 ( *netlister )( schematicPath.GetFullPath(), netlist_str );
1855 }
1856 }
1857
1858 if( netlist_str == annotateMsg )
1859 {
1860 m_reporter->Report( wxString( netlist_str ) + wxT( "\n" ), RPT_SEVERITY_ERROR );
1861 checkParity = false;
1862 }
1863 }
1864
1865 if( checkParity )
1866 {
1867 try
1868 {
1869 STRING_LINE_READER* lineReader = new STRING_LINE_READER( netlist_str,
1870 _( "Eeschema netlist" ) );
1871 KICAD_NETLIST_READER netlistReader( lineReader, netlist.get() );
1872
1873 netlistReader.LoadNetlist();
1874 }
1875 catch( const IO_ERROR& )
1876 {
1877 m_reporter->Report( _( "Failed to fetch schematic netlist for parity tests.\n" ),
1879 checkParity = false;
1880 }
1881
1882 drcEngine->SetSchematicNetlist( netlist.get() );
1883 }
1884
1885 drcEngine->SetProgressReporter( nullptr );
1886 drcEngine->SetViolationHandler(
1887 [&]( const std::shared_ptr<DRC_ITEM>& aItem, VECTOR2I aPos, int aLayer,
1888 DRC_CUSTOM_MARKER_HANDLER* aCustomHandler )
1889 {
1890 PCB_MARKER* marker = new PCB_MARKER( aItem, aPos, aLayer );
1891 commit.Add( marker );
1892 } );
1893
1894 brd->RecordDRCExclusions();
1895 brd->DeleteMARKERs( true, true );
1896 drcEngine->RunTests( units, drcJob->m_reportAllTrackErrors, checkParity );
1897 drcEngine->ClearViolationHandler();
1898
1899 commit.Push( _( "DRC" ), SKIP_UNDO | SKIP_SET_DIRTY );
1900
1901 // Update the exclusion status on any excluded markers that still exist.
1902 brd->ResolveDRCExclusions( false );
1903
1904 std::shared_ptr<DRC_ITEMS_PROVIDER> markersProvider = std::make_shared<DRC_ITEMS_PROVIDER>(
1906
1907 std::shared_ptr<DRC_ITEMS_PROVIDER> ratsnestProvider =
1908 std::make_shared<DRC_ITEMS_PROVIDER>( brd, MARKER_BASE::MARKER_RATSNEST );
1909
1910 std::shared_ptr<DRC_ITEMS_PROVIDER> fpWarningsProvider =
1911 std::make_shared<DRC_ITEMS_PROVIDER>( brd, MARKER_BASE::MARKER_PARITY );
1912
1913 markersProvider->SetSeverities( drcJob->m_severity );
1914 ratsnestProvider->SetSeverities( drcJob->m_severity );
1915 fpWarningsProvider->SetSeverities( drcJob->m_severity );
1916
1917 m_reporter->Report( wxString::Format( _( "Found %d violations\n" ),
1918 markersProvider->GetCount() ),
1920 m_reporter->Report( wxString::Format( _( "Found %d unconnected items\n" ),
1921 ratsnestProvider->GetCount() ),
1923
1924 if( checkParity )
1925 {
1926 m_reporter->Report( wxString::Format( _( "Found %d schematic parity issues\n" ),
1927 fpWarningsProvider->GetCount() ),
1929 }
1930
1931 DRC_REPORT reportWriter( brd, units, markersProvider, ratsnestProvider, fpWarningsProvider );
1932
1933 bool wroteReport = false;
1934
1936 wroteReport = reportWriter.WriteJsonReport( outPath );
1937 else
1938 wroteReport = reportWriter.WriteTextReport( outPath );
1939
1940 if( !wroteReport )
1941 {
1942 m_reporter->Report( wxString::Format( _( "Unable to save DRC report to %s\n" ), outPath ),
1945 }
1946
1947 m_reporter->Report( wxString::Format( _( "Saved DRC Report to %s\n" ), outPath ),
1949
1950 if( drcJob->m_exitCodeViolations )
1951 {
1952 if( markersProvider->GetCount() > 0 || ratsnestProvider->GetCount() > 0
1953 || fpWarningsProvider->GetCount() > 0 )
1954 {
1956 }
1957 }
1958
1960}
1961
1962
1964{
1965 JOB_EXPORT_PCB_IPC2581* job = dynamic_cast<JOB_EXPORT_PCB_IPC2581*>( aJob );
1966
1967 if( job == nullptr )
1969
1970 BOARD* brd = getBoard( job->m_filename );
1971
1972 if( !brd )
1974
1975 aJob->SetTitleBlock( brd->GetTitleBlock() );
1976
1977 if( job->GetConfiguredOutputPath().IsEmpty() )
1978 {
1979 wxFileName fn = brd->GetFileName();
1980 fn.SetName( fn.GetName() );
1981 fn.SetExt( FILEEXT::Ipc2581FileExtension );
1982
1983 job->SetWorkingOutputPath( fn.GetName() );
1984 }
1985
1986 wxString outPath = job->GetFullOutputPath( brd->GetProject() );
1987
1988 if( !PATHS::EnsurePathExists( outPath, true ) )
1989 {
1990 m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
1992 }
1993
1994 std::map<std::string, UTF8> props;
1995 props["units"] = job->m_units == JOB_EXPORT_PCB_IPC2581::IPC2581_UNITS::MILLIMETERS ? "mm"
1996 : "inch";
1997 props["sigfig"] = wxString::Format( "%d", job->m_precision );
1998 props["version"] = job->m_version == JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION::C ? "C" : "B";
1999 props["OEMRef"] = job->m_colInternalId;
2000 props["mpn"] = job->m_colMfgPn;
2001 props["mfg"] = job->m_colMfg;
2002 props["dist"] = job->m_colDist;
2003 props["distpn"] = job->m_colDistPn;
2004
2005 wxString tempFile = wxFileName::CreateTempFileName( wxS( "pcbnew_ipc" ) );
2006 try
2007 {
2009 pi->SetProgressReporter( m_progressReporter );
2010 pi->SaveBoard( tempFile, brd, &props );
2011 }
2012 catch( const IO_ERROR& ioe )
2013 {
2014 m_reporter->Report( wxString::Format( _( "Error generating IPC-2581 file '%s'.\n%s" ),
2015 job->m_filename,
2016 ioe.What() ),
2018
2019 wxRemoveFile( tempFile );
2020
2022 }
2023
2024 if( job->m_compress )
2025 {
2026 wxFileName tempfn = outPath;
2027 tempfn.SetExt( FILEEXT::Ipc2581FileExtension );
2028 wxFileName zipfn = tempFile;
2029 zipfn.SetExt( "zip" );
2030
2031 {
2032 wxFFileOutputStream fnout( zipfn.GetFullPath() );
2033 wxZipOutputStream zip( fnout );
2034 wxFFileInputStream fnin( tempFile );
2035
2036 zip.PutNextEntry( tempfn.GetFullName() );
2037 fnin.Read( zip );
2038 }
2039
2040 wxRemoveFile( tempFile );
2041 tempFile = zipfn.GetFullPath();
2042 }
2043
2044 // If save succeeded, replace the original with what we just wrote
2045 if( !wxRenameFile( tempFile, outPath ) )
2046 {
2047 m_reporter->Report( wxString::Format( _( "Error generating IPC-2581 file '%s'.\n"
2048 "Failed to rename temporary file '%s." ),
2049 outPath,
2050 tempFile ),
2052 }
2053
2055}
2056
2057
2059{
2060 JOB_EXPORT_PCB_ODB* job = dynamic_cast<JOB_EXPORT_PCB_ODB*>( aJob );
2061
2062 if( job == nullptr )
2064
2065 BOARD* brd = getBoard( job->m_filename );
2066
2067 if( !brd )
2069
2070 aJob->SetTitleBlock( brd->GetTitleBlock() );
2071
2072 wxString path = job->GetConfiguredOutputPath();
2073
2074 if( job->GetConfiguredOutputPath().IsEmpty() )
2075 {
2077 {
2078 // just basic folder name
2079 job->SetWorkingOutputPath( "odb" );
2080 }
2081 else
2082 {
2083 wxFileName fn( brd->GetFileName() );
2084 fn.SetName( fn.GetName() + wxS( "-odb" ) );
2085
2086 switch( job->m_compressionMode )
2087 {
2089 fn.SetExt( FILEEXT::ArchiveFileExtension );
2090 break;
2092 fn.SetExt( "tgz" );
2093 break;
2094 default: break;
2095 };
2096
2097 job->SetWorkingOutputPath( fn.GetFullName() );
2098 }
2099 }
2100
2102
2104}
2105
2106
2108{
2110 &aBrd->GetPageSettings(),
2111 aBrd->GetProject(),
2112 &aBrd->GetTitleBlock(),
2113 &aBrd->GetProperties() );
2114
2115 drawingSheet->SetSheetName( std::string() );
2116 drawingSheet->SetSheetPath( std::string() );
2117 drawingSheet->SetIsFirstPage( true );
2118
2119 drawingSheet->SetFileName( TO_UTF8( aBrd->GetFileName() ) );
2120
2121 return drawingSheet;
2122}
2123
2124
2125void PCBNEW_JOBS_HANDLER::loadOverrideDrawingSheet( BOARD* aBrd, const wxString& aSheetPath )
2126{
2127 // dont bother attempting to load a empty path, if there was one
2128 if( aSheetPath.IsEmpty() )
2129 return;
2130
2131 auto loadSheet =
2132 [&]( const wxString& path ) -> bool
2133 {
2136 resolver.SetProject( aBrd->GetProject() );
2138
2140 aBrd->GetProject()->GetProjectPath(),
2141 aBrd->GetEmbeddedFiles() );
2142 wxString msg;
2143
2144 if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename, &msg ) )
2145 {
2146 m_reporter->Report( wxString::Format( _( "Error loading drawing sheet '%s'." ),
2147 path )
2148 + wxS( "\n" ) + msg + wxS( "\n" ),
2150 return false;
2151 }
2152
2153 return true;
2154 };
2155
2156 if( loadSheet( aSheetPath ) )
2157 return;
2158
2159 // failed loading custom path, revert back to default
2160 loadSheet( aBrd->GetProject()->GetProjectFile().m_BoardDrawingSheetFile );
2161}
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:831
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition: board.cpp:2620
const PAGE_INFO & GetPageSettings() const
Definition: board.h:706
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: board.cpp:330
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:712
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1744
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:347
const PCB_PLOT_PARAMS & GetPlotOptions() const
Definition: board.h:709
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:616
PROJECT * GetProject() const
Definition: board.h:505
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:948
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition: board.cpp:2116
void DeleteMARKERs()
Delete all MARKERS from the board.
Definition: board.cpp:1431
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:125
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:2500
void SetLink(const KIID &aLink)
Definition: footprint.h:875
void SetOrientation(const EDA_ANGLE &aNewAngle)
Definition: footprint.cpp:2588
EDA_ITEM * Clone() const override
Invoke a function on all children.
Definition: footprint.cpp:2178
std::deque< PAD * > & Pads()
Definition: footprint.h:204
const LIB_ID & GetFPID() const
Definition: footprint.h:246
void SetPath(const wxString &aPath)
void Save(FOOTPRINT *aFootprintFilter=nullptr)
Save the footprint cache or a single footprint from it to disk.
boost::ptr_map< wxString, FP_CACHE_ENTRY > & GetFootprints()
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 KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition: kiway.cpp:201
@ FACE_SCH
eeschema DSO
Definition: kiway.h:292
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:703
LSEQ SeqStackupForPlotting() const
Return the sequence that is typical for a bottom-to-top stack-up.
Definition: lset.cpp:388
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:575
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:564
@ 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, REPORTER &aReporter)
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 LegacySchematicFileExtension
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 KiCadSchematicFileExtension
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
@ KIFACE_NETLIST_SCHEMATIC
Definition: kiface_ids.h:56
KIID niluuid(0)
@ LAYER_3D_BACKGROUND_TOP
Definition: layer_ids.h:540
@ LAYER_3D_BACKGROUND_BOTTOM
Definition: layer_ids.h:539
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.
#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:403
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
Implement a participant in the KIWAY alchemy.
Definition: kiway.h:152
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