diff --git a/pcbnew/exporters/gerber_jobfile_writer.cpp b/pcbnew/exporters/gerber_jobfile_writer.cpp index 69eedc0565..b10104d025 100644 --- a/pcbnew/exporters/gerber_jobfile_writer.cpp +++ b/pcbnew/exporters/gerber_jobfile_writer.cpp @@ -52,7 +52,6 @@ GERBER_JOBFILE_WRITER::GERBER_JOBFILE_WRITER( BOARD* aPcb, REPORTER* aReporter ) m_pcb = aPcb; m_reporter = aReporter; m_conversionUnits = 1.0 / IU_PER_MM; // Gerber units = mm - m_useJSONformat = true; m_indent = 0; } @@ -120,10 +119,7 @@ bool GERBER_JOBFILE_WRITER::CreateJobFile( const wxString& aFullFilename ) bool success; wxString msg; - if( m_useJSONformat ) - success = CreateJSONJobFile( aFullFilename ); - else - success = CreateGbrJobFile( aFullFilename ); + success = WriteJSONJobFile( aFullFilename ); if( !success ) { @@ -143,269 +139,6 @@ bool GERBER_JOBFILE_WRITER::CreateJobFile( const wxString& aFullFilename ) } -extern void BuildGerberX2Header( const BOARD *aBoard, wxArrayString& aHeader ); - - -bool GERBER_JOBFILE_WRITER::CreateGbrJobFile( const wxString& aFullFilename ) -{ - // Note: in Gerber job file, dimensions are in mm, and are floating numbers - FILE* jobFile = wxFopen( aFullFilename, "wt" ); - - wxString msg; - - if( jobFile == nullptr ) - return false; - - LOCALE_IO dummy; - - // output the job file header - bool hasInnerLayers = m_pcb->GetCopperLayerCount() > 2; - wxArrayString header; - - fputs( "G04 Gerber job file with board parameters*\n" - "%TF.FileFunction,JobInfo*%\n" - "%TF.Part,SinglePCB*%\n", jobFile ); - fputs( "G04 Single PCB fabrication instructions*\n", jobFile ); - - BuildGerberX2Header( m_pcb, header ); - - for( unsigned ii = 0; ii < header.GetCount(); ii++ ) - { - if( header[ii].Contains( "TF.SameCoordinates" ) ) - continue; // This attribute is not useful in job file, skip it - - fputs( TO_UTF8( header[ii] ), jobFile ); - fputs( "\n", jobFile ); - } - - - fputs( "%MOMM*%\n", jobFile ); - - fputs( "G04 Overall board parameters*\n", jobFile ); - // output the bord size in mm: - EDA_RECT brect = m_pcb->GetBoardEdgesBoundingBox(); - fprintf( jobFile, "%%TJ.B_Size_X,%.3f*%%\n", brect.GetWidth()*m_conversionUnits ); - fprintf( jobFile, "%%TJ.B_Size_Y,%.3f*%%\n", brect.GetHeight()*m_conversionUnits ); - - // number of copper layers - fprintf( jobFile, "%%TJ.B_LayerNum,%d*%%\n", m_pcb->GetCopperLayerCount() ); - - // Board thickness - fprintf( jobFile, "%%TJ.B_Overall_Thickness,%.3f*%%\n", - m_pcb->GetDesignSettings().GetBoardThickness()*m_conversionUnits ); - - fprintf( jobFile, "%%TJ.B_Legend_Present,%s*%%\n", sideKeyValue( hasSilkLayers() ) ); - - fprintf( jobFile, "%%TJ.B_SolderMask_Present,%s*%%\n", sideKeyValue( hasSolderMasks() ) ); - - // Job file support a few design rules: - fputs( "G04 board design rules*\n", jobFile ); - const BOARD_DESIGN_SETTINGS& dsnSettings = m_pcb->GetDesignSettings(); - NETCLASS defaultNC = *dsnSettings.GetDefault(); - int minclearanceOuter = defaultNC.GetClearance(); - - // Search a smaller clearance in other net classes, if any. - for( NETCLASSES::const_iterator it = dsnSettings.m_NetClasses.begin(); - it != dsnSettings.m_NetClasses.end(); - ++it ) - { - NETCLASS netclass = *it->second; - minclearanceOuter = std::min( minclearanceOuter, netclass.GetClearance() ); - } - - // job file knows different clearance types. - // Kicad knows only one clearance for pads and tracks - // However, pads can have a specific clearance defined for a pad or a footprint, - // and min clearance can be dependent on layers. - // Search for a minimal pad clearance: - int minPadClearanceOuter = defaultNC.GetClearance(); - int minPadClearanceInner = defaultNC.GetClearance(); - - for( MODULE* module : m_pcb->Modules() ) - { - for( auto& pad : module->Pads() ) - { - if( ( pad->GetLayerSet() & LSET::InternalCuMask() ).any() ) - minPadClearanceInner = std::min( minPadClearanceInner, pad->GetClearance() ); - - if( ( pad->GetLayerSet() & LSET::ExternalCuMask() ).any() ) - minPadClearanceOuter = std::min( minPadClearanceOuter, pad->GetClearance() ); - } - } - - - fprintf( jobFile, "%%TJ.D_PadToPad_Out,%.3f*%%\n", minPadClearanceOuter*m_conversionUnits ); - - if( hasInnerLayers ) - fprintf( jobFile, "%%TJ.D_PadToPad_Inr,%.3f*%%\n", minPadClearanceInner*m_conversionUnits ); - - fprintf( jobFile, "%%TJ.D_PadToTrack_Out,%.3f*%%\n", minPadClearanceOuter*m_conversionUnits ); - - if( hasInnerLayers ) - fprintf( jobFile, "%%TJ.D_PadToTrack_Inr,%.3f*%%\n", minPadClearanceInner*m_conversionUnits ); - - // Until this is changed in Kicad, use the same value for internal tracks - int minclearanceInner = minclearanceOuter; - - fprintf( jobFile, "%%TJ.D_TrackToTrack_Out,%.3f*%%\n", minclearanceOuter*m_conversionUnits ); - - if( hasInnerLayers ) - fprintf( jobFile, "%%TJ.D_TrackToTrack_Inr,%.3f*%%\n", minclearanceInner*m_conversionUnits ); - - // Output the minimal track width - int mintrackWidthOuter = INT_MAX; - int mintrackWidthInner = INT_MAX; - - for( TRACK* track : m_pcb->Tracks() ) - { - if( track->Type() == PCB_VIA_T ) - continue; - - if( track->GetLayer() == B_Cu || track->GetLayer() == F_Cu ) - mintrackWidthOuter = std::min( mintrackWidthOuter, track->GetWidth() ); - else - mintrackWidthInner = std::min( mintrackWidthInner, track->GetWidth() ); - } - - if( mintrackWidthOuter != INT_MAX ) - fprintf( jobFile, "%%TJ.D_MinLineWidth_Out,%.3f*%%\n", mintrackWidthOuter*m_conversionUnits ); - - if( mintrackWidthInner != INT_MAX ) - fprintf( jobFile, "%%TJ.D_MinLineWidth_Inr,%.3f*%%\n", mintrackWidthInner*m_conversionUnits ); - - // Output the minimal zone to xx clearance - // Note: zones can have a zone clearance set to 0 - // if happens, the actual zone clearance is the clearance of its class - minclearanceOuter = INT_MAX; - minclearanceInner = INT_MAX; - - for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ ) - { - ZONE_CONTAINER* zone = m_pcb->GetArea( ii ); - - if( zone->GetIsKeepout() || !zone->IsOnCopperLayer() ) - continue; - - int zclerance = zone->GetClearance(); - - if( zone->GetLayer() == B_Cu || zone->GetLayer() == F_Cu ) - minclearanceOuter = std::min( minclearanceOuter, zclerance ); - else - minclearanceInner = std::min( minclearanceInner, zclerance ); - } - - if( minclearanceOuter != INT_MAX ) - fprintf( jobFile, "%%TJ.D_TrackToRegion_Out,%.3f*%%\n", minclearanceOuter*m_conversionUnits ); - - if( hasInnerLayers && minclearanceInner != INT_MAX ) - fprintf( jobFile, "%%TJ.D_TrackToRegion_Inr,%.3f*%%\n", minclearanceInner*m_conversionUnits ); - - if( minclearanceOuter != INT_MAX ) - fprintf( jobFile, "%%TJ.D_RegionToRegion_Out,%.3f*%%\n", minclearanceOuter*m_conversionUnits ); - - if( hasInnerLayers && minclearanceInner != INT_MAX ) - fprintf( jobFile, "%%TJ.D_RegionToRegion_Inr,%.3f*%%\n", minclearanceInner*m_conversionUnits ); - - // output the gerber file list: - fputs( "G04 Layer Structure*\n", jobFile ); - - for( unsigned ii = 0; ii < m_params.m_GerberFileList.GetCount(); ii ++ ) - { - wxString& name = m_params.m_GerberFileList[ii]; - PCB_LAYER_ID layer = m_params.m_LayerId[ii]; - wxString gbr_layer_id; - bool skip_file = false; // true to skip files which should not be in job file - const char* polarity = "Positive"; - - if( layer <= B_Cu ) - { - gbr_layer_id = "Copper,L"; - - if( layer == B_Cu ) - gbr_layer_id << m_pcb->GetCopperLayerCount(); - else - gbr_layer_id << layer+1; - - gbr_layer_id << ","; - - if( layer == B_Cu ) - gbr_layer_id << "Bot"; - else if( layer == F_Cu ) - gbr_layer_id << "Top"; - else - gbr_layer_id << "Inr"; - } - - else - { - switch( layer ) - { - case B_Adhes: - gbr_layer_id = "Glue,Bot"; break; - case F_Adhes: - gbr_layer_id = "Glue,Top"; break; - - case B_Paste: - gbr_layer_id = "SolderPaste,Bot"; break; - case F_Paste: - gbr_layer_id = "SolderPaste,Top"; break; - - case B_SilkS: - gbr_layer_id = "Legend,Bot"; break; - case F_SilkS: - gbr_layer_id = "Legend,Top"; break; - - case B_Mask: - gbr_layer_id = "SolderMask,Bot"; polarity = "Negative"; break; - case F_Mask: - gbr_layer_id = "SolderMask,Top"; polarity = "Negative"; break; - - case Edge_Cuts: - gbr_layer_id = "Profile"; break; - - case B_Fab: - gbr_layer_id = "AssemblyDrawing,Bot"; break; - case F_Fab: - gbr_layer_id = "AssemblyDrawing,Top"; break; - - case Dwgs_User: - case Cmts_User: - case Eco1_User: - case Eco2_User: - case Margin: - case B_CrtYd: - case F_CrtYd: - skip_file = true; break; - - default: - skip_file = true; - m_reporter->Report( "Unexpected layer id in job file", - REPORTER::RPT_ERROR ); - break; - } - } - - if( !skip_file ) - { - // name can contain non ASCII7 chars. - // Only ASCII7 chars are accepted in gerber files. others must be converted to - // a gerber hexa sequence. - std::string strname = formatStringToGerber( name ); - fprintf( jobFile, "%%TJ.L_\"%s\",%s,%s*%%\n", TO_UTF8( gbr_layer_id ), - polarity, strname.c_str() ); - } - } - - // Close job file - fputs( "M02*\n", jobFile ); - - fclose( jobFile ); - - return true; -} - - - void GERBER_JOBFILE_WRITER::addJSONHeader() { wxString text; @@ -460,7 +193,7 @@ void GERBER_JOBFILE_WRITER::removeJSONSepararator() } } -bool GERBER_JOBFILE_WRITER::CreateJSONJobFile( const wxString& aFullFilename ) +bool GERBER_JOBFILE_WRITER::WriteJSONJobFile( const wxString& aFullFilename ) { // Note: in Gerber job file, dimensions are in mm, and are floating numbers FILE* jobFile = wxFopen( aFullFilename, "wt" ); diff --git a/pcbnew/exporters/gerber_jobfile_writer.h b/pcbnew/exporters/gerber_jobfile_writer.h index 489220398e..89033fbd73 100644 --- a/pcbnew/exporters/gerber_jobfile_writer.h +++ b/pcbnew/exporters/gerber_jobfile_writer.h @@ -93,20 +93,13 @@ public: */ bool CreateJobFile( const wxString& aFullFilename ); - /** - * Creates a Gerber job file in old gbr format - * @param aFullFilename = the full filename - * @return true, or false if the file cannot be created - */ - bool CreateGbrJobFile( const wxString& aFullFilename ); - /** * Creates an Gerber job file in JSON format * @param aFullFilename = the full filename * @param aParams = true for a NPTH file, false for a PTH file * @return true, or false if the file cannot be created */ - bool CreateJSONJobFile( const wxString& aFullFilename ); + bool WriteJSONJobFile( const wxString& aFullFilename ); private: /** @return SIDE_NONE if no silk screen layer is in list @@ -203,6 +196,7 @@ private: { addIndent(); m_JSONbuffer << aParam; } + void addJSONObject( const char* aParam ) { addIndent(); m_JSONbuffer << aParam; @@ -213,7 +207,6 @@ private: REPORTER* m_reporter; // a reporter for messages (can be null) JOBFILE_PARAMS m_params; // the list of various prms and data to write in a job file double m_conversionUnits; // scaling factor to convert brd units to gerber units (mm) - bool m_useJSONformat; // temporary option wxString m_JSONbuffer; // a buffer to build the JSON data int m_indent; // helper for JSON format: the current indentation value };