/** * Function StepAndRepeatItem * Gerber format has a command Step an Repeat * This function must be called when reading a gerber file and * after creating a new gerber item that must be repeated * (i.e when m_XRepeatCount or m_YRepeatCount are > 1) * @param aItem = the item to repeat */ void GERBER_FILE_IMAGE::StepAndRepeatItem( const GERBER_DRAW_ITEM& aItem ) { if( GetLayerParams().m_XRepeatCount < 2 && GetLayerParams().m_YRepeatCount < 2 ) return; // Nothing to repeat // Duplicate item: for( int ii = 0; ii < GetLayerParams().m_XRepeatCount; ii++ ) { for( int jj = 0; jj < GetLayerParams().m_YRepeatCount; jj++ ) { // the first gerber item already exists (this is the template) // create duplicate only if ii or jj > 0 if( jj == 0 && ii == 0 ) continue; GERBER_DRAW_ITEM* dupItem = new GERBER_DRAW_ITEM( aItem ); wxPoint move_vector; move_vector.x = scaletoIU( ii * GetLayerParams().m_StepForRepeat.x, GetLayerParams().m_StepForRepeatMetric ); move_vector.y = scaletoIU( jj * GetLayerParams().m_StepForRepeat.y, GetLayerParams().m_StepForRepeatMetric ); dupItem->MoveXY( move_vector ); m_Drawings.Append( dupItem ); } } }
bool GERBER_IMAGE::ExecuteRS274XCommand( int command, char buff[GERBER_BUFZ], char*& text ) { int code; int xy_seq_len; // not used, provided but not yet in use int xy_seq_char; bool ok = true; char line[GERBER_BUFZ]; wxString msg; double fcoord; // conv_scale = scaling factor from inch to Internal Unit double conv_scale = IU_PER_MILS * 1000; if( m_GerbMetric ) conv_scale /= 25.4; // D( printf( "%22s: Command <%c%c>\n", __func__, (command >> 8) & 0xFF, command & 0xFF ); ) switch( command ) { case FORMAT_STATEMENT: xy_seq_len = 2; while( *text != '*' ) { switch( *text ) { case ' ': text++; break; case 'L': // No Leading 0 m_DecimalFormat = false; m_NoTrailingZeros = false; text++; break; case 'T': // No trailing 0 m_DecimalFormat = false; m_NoTrailingZeros = true; text++; break; case 'D': // Decimal format: sometimes found, but not really documented m_DecimalFormat = true; text++; break; case 'A': // Absolute coord m_Relative = false; text++; break; case 'I': // Relative coord m_Relative = true; text++; break; case 'N': // Sequence code (followed by the number of digits // for the X,Y command text++; xy_seq_char = *text++; if( (xy_seq_char >= '0') && (xy_seq_char <= '9') ) xy_seq_len = -'0'; break; case 'X': case 'Y': // Values transmitted :2 (really xy_seq_len : // digits { code = *(text++); char ctmp = *(text++) - '0'; if( code == 'X' ) { xy_seq_len--; // number of digits after the decimal point (0 to 6 allowed) m_FmtScale.x = *text - '0'; m_FmtLen.x = ctmp + m_FmtScale.x; // m_FmtScale is 0 to 6 if( m_FmtScale.x < 0 ) m_FmtScale.x = 0; if( m_FmtScale.x > 6 ) m_FmtScale.x = 6; } else { xy_seq_len--; m_FmtScale.y = *text - '0'; m_FmtLen.y = ctmp + m_FmtScale.y; if( m_FmtScale.y < 0 ) m_FmtScale.y = 0; if( m_FmtScale.y > 6 ) m_FmtScale.y = 6; } text++; } break; case '*': break; default: GetEndOfBlock( buff, text, m_Current_File ); ok = false; break; } } if( xy_seq_len != 0 ) { ReportMessage( wxT( "RS274X: suspicious Format Statement (FS) command" ) ); } break; case AXIS_SELECT: // command ASAXBY*% or %ASAYBX*% m_SwapAxis = false; if( strnicmp( text, "AYBX", 4 ) == 0 ) m_SwapAxis = true; break; case MIRROR_IMAGE: // commanf %MIA0B0*%, %MIA0B1*%, %MIA1B0*%, %MIA1B1*% m_MirrorA = m_MirrorB = 0; while( *text && *text != '*' ) { switch( *text ) { case 'A': // Mirror A axis ? text++; if( *text == '1' ) m_MirrorA = true; break; case 'B': // Mirror B axis ? text++; if( *text == '1' ) m_MirrorB = true; break; default: text++; break; } } break; case MODE_OF_UNITS: code = ReadXCommand( text ); if( code == INCH ) m_GerbMetric = false; else if( code == MILLIMETER ) m_GerbMetric = true; conv_scale = m_GerbMetric ? IU_PER_MILS / 25.4 : IU_PER_MILS; break; case OFFSET: // command: OFAnnBnn (nn = float number) = layer Offset m_Offset.x = m_Offset.y = 0; while( *text != '*' ) { switch( *text ) { case 'A': // A axis offset in current unit (inch or mm) text++; fcoord = ReadDouble( text ); m_Offset.x = KiROUND( fcoord * conv_scale ); break; case 'B': // B axis offset in current unit (inch or mm) text++; fcoord = ReadDouble( text ); m_Offset.y = KiROUND( fcoord * conv_scale ); break; } } break; case SCALE_FACTOR: m_Scale.x = m_Scale.y = 1.0; while( *text != '*' ) { switch( *text ) { case 'A': // A axis scale text++; m_Scale.x = ReadDouble( text ); break; case 'B': // B axis scale text++; m_Scale.y = ReadDouble( text ); break; } } break; case IMAGE_OFFSET: // command: IOAnnBnn (nn = float number) = Image Offset m_ImageOffset.x = m_ImageOffset.y = 0; while( *text != '*' ) { switch( *text ) { case 'A': // A axis offset in current unit (inch or mm) text++; fcoord = ReadDouble( text ); m_ImageOffset.x = KiROUND( fcoord * conv_scale ); break; case 'B': // B axis offset in current unit (inch or mm) text++; fcoord = ReadDouble( text ); m_ImageOffset.y = KiROUND( fcoord * conv_scale ); break; } } break; case IMAGE_ROTATION: // command IR0* or IR90* or IR180* or IR270* if( strnicmp( text, "0*", 2 ) == 0 ) m_ImageRotation = 0; if( strnicmp( text, "90*", 2 ) == 0 ) m_ImageRotation = 90; if( strnicmp( text, "180*", 2 ) == 0 ) m_ImageRotation = 180; if( strnicmp( text, "270*", 2 ) == 0 ) m_ImageRotation = 270; else ReportMessage( _( "RS274X: Command \"IR\" rotation value not allowed" ) ); break; case STEP_AND_REPEAT: // command SR, like %SRX3Y2I5.0J2*% m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Start a new Gerber layer GetLayerParams().m_StepForRepeat.x = 0.0; GetLayerParams().m_StepForRepeat.x = 0.0; // offset for Step and Repeat command GetLayerParams().m_XRepeatCount = 1; GetLayerParams().m_YRepeatCount = 1; // The repeat count GetLayerParams().m_StepForRepeatMetric = m_GerbMetric; // the step units while( *text && *text != '*' ) { switch( *text ) { case 'I': // X axis offset text++; GetLayerParams().m_StepForRepeat.x = ReadDouble( text ); break; case 'J': // Y axis offset text++; GetLayerParams().m_StepForRepeat.y = ReadDouble( text ); break; case 'X': // X axis repeat count text++; GetLayerParams().m_XRepeatCount = ReadInt( text ); break; case 'Y': // Y axis offset text++; GetLayerParams().m_YRepeatCount = ReadInt( text ); break; default: text++; break; } } break; case IMAGE_JUSTIFY: // Command IJAnBn* m_ImageJustifyXCenter = false; // Image Justify Center on X axis (default = false) m_ImageJustifyYCenter = false; // Image Justify Center on Y axis (default = false) m_ImageJustifyOffset = wxPoint(0,0); // Image Justify Offset on XY axis (default = 0,0) while( *text && *text != '*' ) { // IJ command is (for A or B axis) AC or AL or A<coordinate> switch( *text ) { case 'A': // A axis justify text++; if( *text == 'C' ) { m_ImageJustifyXCenter = true; text++; } else if( *text == 'L' ) { m_ImageJustifyXCenter = true; text++; } else m_ImageJustifyOffset.x = KiROUND( ReadDouble( text ) * conv_scale); break; case 'B': // B axis justify text++; if( *text == 'C' ) { m_ImageJustifyYCenter = true; text++; } else if( *text == 'L' ) { m_ImageJustifyYCenter = true; text++; } else m_ImageJustifyOffset.y = KiROUND( ReadDouble( text ) * conv_scale); break; default: text++; break; } } if( m_ImageJustifyXCenter ) m_ImageJustifyOffset.x = 0; if( m_ImageJustifyYCenter ) m_ImageJustifyOffset.y = 0; break; case KNOCKOUT: m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Start a new Gerber layer msg = _( "RS274X: Command KNOCKOUT ignored by GerbView" ) ; ReportMessage( msg ); break; case PLOTTER_FILM: // Command PF <string> // This is an info about film that must be used to plot this file // Has no meaning here. We just display this string msg = wxT( "Plotter Film info:<br>" ); while( *text != '*' ) { msg.Append( *text++ ); } ReportMessage( msg ); break; case ROTATE: // Layer rotation: command like %RO45*% m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Start a new Gerber layer m_LocalRotation =ReadDouble( text ); // Store layer rotation in degrees break; case IMAGE_NAME: m_ImageName.Empty(); while( *text != '*' ) { m_ImageName.Append( *text++ ); } break; case LAYER_NAME: m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Start a new Gerber layer GetLayerParams( ).m_LayerName.Empty(); while( *text != '*' ) { GetLayerParams( ).m_LayerName.Append( *text++ ); } break; case IMAGE_POLARITY: if( strnicmp( text, "NEG", 3 ) == 0 ) m_ImageNegative = true; else m_ImageNegative = false; D( printf( "%22s: IMAGE_POLARITY m_ImageNegative=%s\n", __func__, m_ImageNegative ? "true" : "false" ); ) break; case LAYER_POLARITY: if( *text == 'C' ) GetLayerParams().m_LayerNegative = true; else GetLayerParams().m_LayerNegative = false; D( printf( "%22s: LAYER_POLARITY m_LayerNegative=%s\n", __func__, GetLayerParams().m_LayerNegative ? "true" : "false" ); ) break;