/**
 * 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 );
        }
    }
}
Example #2
0
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;