diff --git a/common/common_plotGERBER_functions.cpp b/common/common_plotGERBER_functions.cpp index 2646171faf..a2a912f025 100644 --- a/common/common_plotGERBER_functions.cpp +++ b/common/common_plotGERBER_functions.cpp @@ -117,9 +117,10 @@ bool GERBER_PLOTTER::StartPlot() if( outputFile == NULL ) return false; - if( ! m_attribFunction.IsEmpty() ) + for( unsigned ii = 0; ii < m_headerExtraLines.GetCount(); ii++ ) { - fprintf( outputFile, "%s\n", TO_UTF8( m_attribFunction ) ); + if( ! m_headerExtraLines[ii].IsEmpty() ) + fprintf( outputFile, "%s\n", TO_UTF8( m_headerExtraLines[ii] ) ); } // Set coordinate format to 3.6 or 4.5 absolute, leading zero omitted diff --git a/common/page_layout/class_worksheet_dataitem.cpp b/common/page_layout/class_worksheet_dataitem.cpp index 6032f39ef3..b5e673f885 100644 --- a/common/page_layout/class_worksheet_dataitem.cpp +++ b/common/page_layout/class_worksheet_dataitem.cpp @@ -465,7 +465,7 @@ void WORKSHEET_DATAITEM_TEXT::IncrementLabel( int aIncr ) // Replace the '\''n' sequence by EOL // and the sequence '\''\' by only one '\' in m_FullText -// if m_FullTextis a multiline text (i;e.contains '\n') return true +// if m_FullText is a multiline text (i.e.contains '\n') return true bool WORKSHEET_DATAITEM_TEXT::ReplaceAntiSlashSequence() { bool multiline = false; diff --git a/include/plot_common.h b/include/plot_common.h index 1c24afcc33..d15693265c 100644 --- a/include/plot_common.h +++ b/include/plot_common.h @@ -142,9 +142,28 @@ public: virtual void SetDash( bool dashed ) = 0; - virtual void SetCreator( const wxString& _creator ) + virtual void SetCreator( const wxString& aCreator ) { - creator = _creator; + creator = aCreator; + } + + /** + * Function AddLineToHeader + * Add a line to the list of free lines to print at the beginning of the file + * @param aExtraString is the string to print + */ + void AddLineToHeader( const wxString& aExtraString ) + { + m_headerExtraLines.Add( aExtraString ); + } + + /** + * Function ClearHeaderLinesList + * remove all lines from the list of free lines to print at the beginning of the file + */ + void ClearHeaderLinesList() + { + m_headerExtraLines.Clear(); } /** @@ -324,11 +343,6 @@ public: // NOP for most plotters. } - virtual void SetLayerAttribFunction( const wxString& function ) - { - // NOP for most plotters. Only for Gerber plotter - } - virtual void SetGerberCoordinatesFormat( int aResolution, bool aUseInches = false ) { // NOP for most plotters. Only for Gerber plotter @@ -406,6 +420,7 @@ protected: double GetDashGapLenIU() const; +protected: // variables used in most of plotters: /// Plot scale - chosen by the user (even implicitly with 'fit in a4') double plotScale; @@ -444,6 +459,8 @@ protected: PAGE_INFO pageInfo; /// Paper size in IU - not in mils wxSize paperSize; + + wxArrayString m_headerExtraLines; /// a set of string to print in header file }; @@ -943,11 +960,6 @@ public: */ virtual void SetLayerPolarity( bool aPositive ); - virtual void SetLayerAttribFunction( const wxString& function ) - { - m_attribFunction = function; - } - /** * Function SetGerberCoordinatesFormat * selection of Gerber units and resolution (number of digits in mantissa) @@ -985,8 +997,6 @@ protected: std::vector apertures; std::vector::iterator currentAperture; - wxString m_attribFunction; // the layer "function", in GERBER X2 extention - // it is linked with the layer id bool m_gerberUnitInch; // true if the gerber units are inches, false for mm int m_gerberUnitFmt; // number of digits in mantissa. // usually 6 in Inches and 5 or 6 in mm diff --git a/kicad/menubar.cpp b/kicad/menubar.cpp index 0aa4baeee4..be8b702962 100644 --- a/kicad/menubar.cpp +++ b/kicad/menubar.cpp @@ -143,14 +143,16 @@ static EDA_HOTKEY HkNewProject( _HKI( "New Project" ), HK_NEW_PRJ, 'N' + GR_KB_C static EDA_HOTKEY HkNewPrjFromTemplate( _HKI( "New Prj From Template" ), HK_NEW_PRJ_TEMPLATE, 'T' + GR_KB_CTRL ); -static EDA_HOTKEY HkRunEeschema( _HKI( "Run Eeschema" ), HK_RUN_EESCHEMA, 'E', 0 ); -static EDA_HOTKEY HkRunLibedit( _HKI( "Run LibEdit" ), HK_RUN_LIBEDIT, 'L', 0 ); -static EDA_HOTKEY HkRunPcbnew( _HKI( "Run Pcbnew" ), HK_RUN_PCBNEW, 'P', 0 ); -static EDA_HOTKEY HkRunModedit( _HKI( "Run FpEditor" ), HK_RUN_FPEDITOR, 'F', 0 ); -static EDA_HOTKEY HkRunGerbview( _HKI( "Run Gerbview" ), HK_RUN_GERBVIEW, 'G', 0 ); -static EDA_HOTKEY HkRunBm2Cmp( _HKI( "Run Bitmap2Component" ), HK_RUN_BM2COMPONENT, 'B', 0 ); -static EDA_HOTKEY HkRunPcbCalc( _HKI( "Run PcbCalculator" ), HK_RUN_PCBCALCULATOR, 'C', 0 ); -static EDA_HOTKEY HkRunPleditor( _HKI( "Run PlEditor" ), HK_RUN_PLEDITOR, 'Y', 0 ); +static EDA_HOTKEY HkRunEeschema( _HKI( "Run Eeschema" ), HK_RUN_EESCHEMA, 'E' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunLibedit( _HKI( "Run LibEdit" ), HK_RUN_LIBEDIT, 'L' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunPcbnew( _HKI( "Run Pcbnew" ), HK_RUN_PCBNEW, 'P' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunModedit( _HKI( "Run FpEditor" ), HK_RUN_FPEDITOR, 'F' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunGerbview( _HKI( "Run Gerbview" ), HK_RUN_GERBVIEW, 'G' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunBm2Cmp( _HKI( "Run Bitmap2Component" ), + HK_RUN_BM2COMPONENT, 'B' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunPcbCalc( _HKI( "Run PcbCalculator" ), + HK_RUN_PCBCALCULATOR, 'C' + GR_KB_CTRL, 0 ); +static EDA_HOTKEY HkRunPleditor( _HKI( "Run PlEditor" ), HK_RUN_PLEDITOR, 'Y' + GR_KB_CTRL, 0 ); // List of hotkey descriptors EDA_HOTKEY* common_Hotkey_List[] = diff --git a/pcbnew/pcbplot.cpp b/pcbnew/pcbplot.cpp index 76028d145e..43a89c961d 100644 --- a/pcbnew/pcbplot.cpp +++ b/pcbnew/pcbplot.cpp @@ -1,9 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -42,6 +42,7 @@ #include #include #include +#include const wxString GetGerberExtension( LAYER_NUM aLayer ) @@ -84,8 +85,8 @@ const wxString GetGerberExtension( LAYER_NUM aLayer ) } -wxString GetGerberFileFunction( const BOARD *aBoard, LAYER_NUM aLayer, - bool aUseX1CompatibilityMode ) +wxString GetGerberFileFunctionAttribute( const BOARD *aBoard, + LAYER_NUM aLayer, bool aUseX1CompatibilityMode ) { wxString attrib; @@ -146,6 +147,14 @@ wxString GetGerberFileFunction( const BOARD *aBoard, LAYER_NUM aLayer, attrib = wxString( wxT( "Other,ECO2" ) ); break; + case B_Fab: + attrib = wxString( wxT( "Other,Fab,Bot" ) ); + break; + + case F_Fab: + attrib = wxString( wxT( "Other,Fab,Top" ) ); + break; + case B_Cu: attrib = wxString::Format( wxT( "Copper,L%d,Bot" ), aBoard->GetCopperLayerCount() ); break; @@ -156,9 +165,9 @@ wxString GetGerberFileFunction( const BOARD *aBoard, LAYER_NUM aLayer, default: if( IsCopperLayer( aLayer ) ) - { attrib = wxString::Format( wxT( "Copper,L%d,Inr" ), aLayer+1 ); - } + else + attrib = wxString::Format( wxT( "Other,User" ), aLayer+1 ); break; } @@ -193,6 +202,95 @@ wxString GetGerberFileFunction( const BOARD *aBoard, LAYER_NUM aLayer, return fileFct; } +/* Add some X2 attributes to the file header, as defined in the + * Gerber file format specification J4 and J5 + */ +#define USE_J5_ATTR +void AddGerberX2Attribute( PLOTTER * aPlotter, + const BOARD *aBoard, LAYER_NUM aLayer ) +{ + wxString text; + +#ifdef USE_J5_ATTR + text = wxT("%TF.GerberVersion,J5*%"); +#else + text = wxT("%TF.GerberVersion,J4*%"); +#endif + aPlotter->AddLineToHeader( text ); + +#ifdef USE_J5_ATTR + // Creates the TF,.GenerationSoftware. Format is: + // %TF,.GenerationSoftware,,[,]*% + text.Printf( wxT( "%TF.GenerationSoftware,KiCad,Pcbnew,%s*%%" ), GetBuildVersion() ); + aPlotter->AddLineToHeader( text ); + + // creates the TF.CreationDate ext: + // The attribute value must conform to the full version of the ISO 8601 + // date and time format, including time and time zone. Note that this is + // the date the Gerber file was effectively created, + // not the time the project of PCB was started + wxDateTime date( wxDateTime::GetTimeNow() ); + // Date format: see http://www.cplusplus.com/reference/ctime/strftime + wxString msg = date.Format( wxT( "%z" ) ); // Extract the time zone offset + // The time zone offset format is + (or -) mm or hhmm (mm = number of minutes, hh = number of hours) + // we want +(or -) hh:mm + if( msg.Len() > 3 ) + msg.insert( 3, ":", 1 ), + text.Printf( wxT( "%TF.CreationDate,%s%s*%%" ), GetChars( date.FormatISOCombined() ), GetChars( msg ) ); + aPlotter->AddLineToHeader( text ); + + // Creates the TF,.JobID. Format is (from Gerber file format doc): + // %TF.JobID,,,*% + // is the name of the project, restricted to basic ASCII symbols only, + // and comma not accepted + // All illegal chars will be replaced by underscore + // is a 32 hexadecimal digits string which is an unique id of a project. + // This is a random 128-bit number expressed in 32 hexadecimal digits. + // See en.wikipedia.org/wiki/GUID for more information + // However Kicad does not handle such a project GUID, so it is built from the board name + // Rem: accepts only ASCII 7 code (only basic ASCII codes are allowed in gerber files). + wxFileName fn = aBoard->GetFileName(); + msg = fn.GetFullName(); + wxString guid; + + // Build a 32 digits GUID from the board name: + for( unsigned ii = 0; ii < msg.Len(); ii++ ) + { + int cc1 = int( msg[ii] ) & 0x0F; + int cc2 = ( int( msg[ii] ) >> 4) & 0x0F; + guid << wxString::Format( wxT( "%X%X" ), cc2, cc1 ); + + if( guid.Len() >= 32 ) + break; + } + + // guid has 32 digits, so add missing digits + int cnt = 32 - guid.Len(); + + if( cnt > 0 ) + guid.Append( '0', cnt ); + + // build the string: this is the board short filename (without ext) + // and all non ASCII chars and comma are replaced by '_' + msg = fn.GetName(); + msg.Replace( wxT( "," ), wxT( "_" ) ); + + // build the string. All non ASCII chars and comma are replaced by '_' + wxString rev = ((BOARD*)aBoard)->GetTitleBlock().GetRevision(); + rev.Replace( wxT( "," ), wxT( "_" ) ); + + if( rev.IsEmpty() ) + rev = wxT( "rev?" ); + + text.Printf( wxT( "%TF.JobID,%s,%s,%s*%%" ), msg.ToAscii(), GetChars( guid ), rev.ToAscii() ); + aPlotter->AddLineToHeader( text ); +#endif + + // Add the TF.FileFunction + text = GetGerberFileFunctionAttribute( aBoard, aLayer, false ); + aPlotter->AddLineToHeader( text ); +} + void BuildPlotFileName( wxFileName* aFilename, const wxString& aOutputDir, diff --git a/pcbnew/pcbplot.h b/pcbnew/pcbplot.h index 3efcef7116..b71b5bdb30 100644 --- a/pcbnew/pcbplot.h +++ b/pcbnew/pcbplot.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -252,9 +252,9 @@ void BuildPlotFileName( wxFileName* aFilename, const wxString GetGerberExtension( LAYER_NUM aLayer ); /** - * Function GetGerberFileFunction + * Function GetGerberFileFunctionAttribute * Returns the "file function" attribute for \a aLayer, as defined in the - * Gerber file format specification J1 (chapter 5). The returned string excludes + * Gerber file format specification J1 (chapter 5). The returned string includes * the "%TF.FileFunction" attribute prefix and the "*%" suffix. * @param aBoard = the board, needed to get the total count of copper layers * @param aLayer = the layer number to create the attribute for @@ -262,10 +262,18 @@ const wxString GetGerberExtension( LAYER_NUM aLayer ); * , compatible with X1 (rx274) notation (G04#@!TF.FileFunction) * @return The attribute, as a text string */ -extern wxString GetGerberFileFunction( const BOARD *aBoard, LAYER_NUM aLayer, - bool aUseX1CompatibilityMode ); +extern wxString GetGerberFileFunctionAttribute( const BOARD *aBoard, + LAYER_NUM aLayer, bool aUseX1CompatibilityMode ); -// PLOTGERB.CPP -void SelectD_CODE_For_LineDraw( PLOTTER* plotter, int aSize ); +/** + * Function AddGerberX2Attribute + * Calculates some X2 attributes, as defined in the + * Gerber file format specification J4 (chapter 5) and add them + * the to the gerber file header + * @param aPlotter, the current plotter. + * @param aBoard = the board, needed to extract some info + * @param aLayer = the layer number to create the attribute for + */ +extern void AddGerberX2Attribute( PLOTTER * aPlotter, const BOARD *aBoard, LAYER_NUM aLayer ); #endif // PCBPLOT_H_ diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index c796ee844e..64843da411 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -8,7 +8,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -142,7 +142,7 @@ void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, } void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, LAYER_ID aLayer, - const PCB_PLOT_PARAMS& aPlotOpt ) + const PCB_PLOT_PARAMS& aPlotOpt ) { PCB_PLOT_PARAMS plotOpt = aPlotOpt; int soldermask_min_thickness = aBoard->GetDesignSettings().m_SolderMaskMinWidth; @@ -1044,12 +1044,18 @@ PLOTTER* StartPlotBoard( BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, if( plotter->OpenFile( aFullFileName ) ) { + plotter->ClearHeaderLinesList(); + // For the Gerber "file function" attribute, set the layer number if( plotter->GetPlotterType() == PLOT_FORMAT_GERBER ) { bool useX2mode = plotOpts.GetUseGerberAttributes(); - plotter->SetLayerAttribFunction( GetGerberFileFunction( aBoard, aLayer, - useX2mode ? false : true ) ); + + if( useX2mode ) + AddGerberX2Attribute( plotter, aBoard, aLayer ); + else + plotter->AddLineToHeader( GetGerberFileFunctionAttribute( + aBoard, aLayer, true ) ); } plotter->StartPlot();