void AddGerberX2Attribute( PLOTTER * aPlotter, const BOARD *aBoard, LAYER_NUM aLayer, bool aUseX1CompatibilityMode ) { AddGerberX2Header( aPlotter, aBoard, aUseX1CompatibilityMode ); wxString text; // Add the TF.FileFunction text = GetGerberFileFunctionAttribute( aBoard, aLayer ); aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) ); // Add the TF.FilePolarity (for layers which support that) text = GetGerberFilePolarityAttribute( aLayer ); if( !text.IsEmpty() ) aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) ); }
void AddGerberX2Attribute( PLOTTER * aPlotter, const BOARD *aBoard, LAYER_NUM aLayer, bool aUseX1CompatibilityMode ) { wxString text; // Creates the TF,.GenerationSoftware. Format is: // %TF,.GenerationSoftware,<vendor>,<application name>[,<application version>]*% text.Printf( wxT( "%%TF.GenerationSoftware,KiCad,Pcbnew,%s*%%" ), GetBuildVersion() ); aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) ); // 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( makeStringCompatX1( text, aUseX1CompatibilityMode ) ); // Creates the TF,.ProjectId. Format is (from Gerber file format doc): // %TF.ProjectId,<project id>,<project GUID>,<revision id>*% // <project id> is the name of the project, restricted to basic ASCII symbols only, // and comma not accepted // All illegal chars will be replaced by underscore // <project GUID> 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: <project id> 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 <project id> 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 <rec> 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.ProjectId,%s,%s,%s*%%" ), msg.ToAscii(), GetChars( guid ), rev.ToAscii() ); aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) ); // Add the TF.FileFunction text = GetGerberFileFunctionAttribute( aBoard, aLayer ); aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) ); // Add the TF.FilePolarity (for layers which support that) text = GetGerberFilePolarityAttribute( aLayer ); if( !text.IsEmpty() ) aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) ); }
/** Open a new plotfile using the options (and especially the format) * specified in the options and prepare the page for plotting. * Return the plotter object if OK, NULL if the file is not created * (or has a problem) */ PLOTTER* StartPlotBoard( BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, int aLayer, const wxString& aFullFileName, const wxString& aSheetDesc ) { // Create the plotter driver and set the few plotter specific // options PLOTTER* plotter = NULL; switch( aPlotOpts->GetFormat() ) { case PLOT_FORMAT_DXF: plotter = new DXF_PLOTTER(); break; case PLOT_FORMAT_POST: PS_PLOTTER* PS_plotter; PS_plotter = new PS_PLOTTER(); PS_plotter->SetScaleAdjust( aPlotOpts->GetFineScaleAdjustX(), aPlotOpts->GetFineScaleAdjustY() ); plotter = PS_plotter; break; case PLOT_FORMAT_PDF: plotter = new PDF_PLOTTER(); break; case PLOT_FORMAT_HPGL: HPGL_PLOTTER* HPGL_plotter; HPGL_plotter = new HPGL_PLOTTER(); /* HPGL options are a little more convoluted to compute, so they're split in an other function */ ConfigureHPGLPenSizes( HPGL_plotter, aPlotOpts ); plotter = HPGL_plotter; break; case PLOT_FORMAT_GERBER: plotter = new GERBER_PLOTTER(); break; case PLOT_FORMAT_SVG: plotter = new SVG_PLOTTER(); break; default: wxASSERT( false ); return NULL; } // Compute the viewport and set the other options // page layout is not mirrored, so temporary change mirror option // just to plot the page layout PCB_PLOT_PARAMS plotOpts = *aPlotOpts; if( plotOpts.GetPlotFrameRef() && plotOpts.GetMirror() ) plotOpts.SetMirror( false ); initializePlotter( plotter, aBoard, &plotOpts ); 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(); if( useX2mode ) AddGerberX2Attribute( plotter, aBoard, aLayer ); else plotter->AddLineToHeader( GetGerberFileFunctionAttribute( aBoard, aLayer, true ) ); } plotter->StartPlot(); // Plot the frame reference if requested if( aPlotOpts->GetPlotFrameRef() ) { PlotWorkSheet( plotter, aBoard->GetTitleBlock(), aBoard->GetPageSettings(), 1, 1, // Only one page aSheetDesc, aBoard->GetFileName() ); if( aPlotOpts->GetMirror() ) initializePlotter( plotter, aBoard, aPlotOpts ); } /* When plotting a negative board: draw a black rectangle * (background for plot board in white) and switch the current * color to WHITE; note the color inversion is actually done * in the driver (if supported) */ if( aPlotOpts->GetNegative() ) { EDA_RECT bbox = aBoard->ComputeBoundingBox(); FillNegativeKnockout( plotter, bbox ); } return plotter; } delete plotter; return NULL; }