Commit 26736baa authored by dickelbeck's avatar dickelbeck
Browse files

gerbview cleanup, and working towards aperture macro support

parent eac91489
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -5,6 +5,17 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with
email address.

2008-Nov-8 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
+gerview
    Added support for reading in aperture macros embedded in a RS274X compatible file.
    Cannot display them yet.
    General cleanup of gerbview.  GERBER_Descr replaced with class GERBER.
    ReturnToolDescr() replaced with GERBER::GetDCODE().
    D_CODEs are created lazily now.  pcbnew's gerber plotting needs testing, might
    have broke something there, accidentally.


2008-nov-5 UPDATE Andrey Fedorushkov <andrf@mail.ru>
================================================================================
+all:
+3 −58
Original line number Diff line number Diff line
@@ -58,58 +58,3 @@ void Affiche_Infos_PCB_Texte( WinEDA_BasePcbFrame* frame, TEXTE_PCB* pt_texte )
    Affiche_1_Parametre( frame, 70, _( "V Size" ), Line, RED );
}

/*********************************************************************/
void Affiche_Infos_Piste( WinEDA_BasePcbFrame* frame, TRACK* pt_piste )
/*********************************************************************/
/* Affiche les caract principales d'un segment de piste en bas d'ecran */
{
    int      d_index, ii = -1;
    D_CODE*  pt_D_code;
	
    int      layer = ((PCB_SCREEN*)(frame->GetScreen()))->m_Active_Layer; 
    wxString msg;

    frame->MsgPanel->EraseMsgBox();

    d_index   = pt_piste->GetNet();
    pt_D_code = ReturnToolDescr( layer, d_index, &ii );

    switch( pt_piste->Type() )
    {
    case TYPETRACK:
        if( pt_piste->m_Shape < S_SPOT_CIRCLE )
            msg = wxT( "LINE" );
        else
            msg = wxT( "FLASH" );
        break;

    case TYPEZONE:
        msg = wxT( "ZONE" ); break;

    default:
        msg = wxT( "????" ); break;
    }

    Affiche_1_Parametre( frame, 1, _( "Type" ), msg, DARKCYAN );

    msg.Printf( wxT( "%d" ), ii + 1 );
    Affiche_1_Parametre( frame, 10, _( "Tool" ), msg, RED );

    if( pt_D_code )
    {
        msg.Printf( wxT( "D%d" ), d_index );
        Affiche_1_Parametre( frame, 20, _( "D-code" ), msg, BLUE );

        Affiche_1_Parametre( frame, 30, _( "D-type" ),
                             pt_D_code ? g_GERBER_Tool_Type[pt_D_code->m_Shape] : _( "????" ),
                             BLUE );
    }

    msg.Printf( wxT( "%d" ), pt_piste->GetLayer() + 1 );
    Affiche_1_Parametre( frame, 40, _( "Layer" ), msg, BROWN );

    /* Affiche Epaisseur */
    valeur_param( (unsigned) (pt_piste->m_Width), msg );
    Affiche_1_Parametre( frame, 50, _( "Width" ), msg, DARKCYAN );
}
+102 −75
Original line number Diff line number Diff line
@@ -63,34 +63,64 @@
    D10 ... = Indentification d'outils ( d'ouvertures )
*/


/*********************************/
/* class GERBER : Methodes */
/*********************************/

GERBER::GERBER( int layer )
GERBER::GERBER( int aLayer )
{
    int ii;
    m_Layer = aLayer;            // Layer Number

    m_Layer = layer;            // Layer Number
    m_Selected_Tool = FIRST_DCODE;

    ResetDefaultValues();
    for( ii = 0; ii <= MAX_TOOLS; ii++ )
        m_Aperture_List[ii] = new D_CODE( ii + FIRST_DCODE );

    for( unsigned ii = 0; ii < DIM( m_Aperture_List );  ii++ )
        m_Aperture_List[ii] = 0;
}


GERBER::~GERBER()
{
    int ii;
    for( unsigned ii = 0; ii < DIM(m_Aperture_List); ii++ )
    {
        delete m_Aperture_List[ii];
        // m_Aperture_List[ii] = NULL;
    }
}


    if( m_Aperture_List )
D_CODE* GERBER::GetDCODE( int aDCODE, bool create )
{
        for( ii = 0; ii < MAX_TOOLS; ii++ )
    unsigned ndx = aDCODE - FIRST_DCODE;

    if( ndx < (unsigned) DIM(m_Aperture_List) )
    {
            delete m_Aperture_List[ii];
            m_Aperture_List[ii] = NULL;
        // lazily create the D_CODE if it does not exist.
        if( create )
        {
            if( m_Aperture_List[ndx] == NULL )
                m_Aperture_List[ndx] = new D_CODE( ndx + FIRST_DCODE );
        }

        return m_Aperture_List[ndx];
    }
    return NULL;
}


APERTURE_MACRO* GERBER::FindApertureMacro( const APERTURE_MACRO& aLookup )
{
    APERTURE_MACRO_SET::iterator iter = m_aperture_macros.find( aLookup );

    if( iter != m_aperture_macros.end() )
    {
        APERTURE_MACRO* pam = (APERTURE_MACRO*) &(*iter);
        return pam;
    }

    return NULL;    // not found
}


@@ -107,8 +137,9 @@ void GERBER::ResetDefaultValues()
    m_NoTrailingZeros = FALSE;          // True: zeros a droite supprim�s
    m_MirorA   = FALSE;                 // True: miror / axe A (X)
    m_MirorB   = FALSE;                 // True: miror / axe B (Y)
    m_As_DCode = FALSE;                 // TRUE = DCodes in file (FALSE = no DCode->
    m_Has_DCode = FALSE;                // TRUE = DCodes in file (FALSE = no DCode->
                                        // separate DCode file

    m_Offset.x = m_Offset.y = 0;        // Coord Offset

    m_FmtScale.x = m_FmtScale.y = g_Default_GERBER_Format % 10;
@@ -136,36 +167,27 @@ void GERBER::ResetDefaultValues()
int GERBER::ReturnUsedDcodeNumber()
/********************************************/
{
    int ii, jj;
    int count = 0;

    jj = 0;
    if( m_Aperture_List )
    {
        for( ii = 0; ii < MAX_TOOLS; ii++ )
    for( unsigned ii = 0; ii < DIM(m_Aperture_List); ii++ )
    {
        if( m_Aperture_List[ii] )
            if( m_Aperture_List[ii]->m_InUse || m_Aperture_List[ii]->m_Defined )
                jj++;
                ++count;
    }
    }
    return jj;
    return count;
}


/******************************/
void GERBER::InitToolTable()
/******************************/

/* Creation du tableau des MAX_TOOLS DCodes utilisables, si il n'existe pas,
  * et Init des DCodes � une valeur raisonnable
 */
{
    int count;

    /* Init du buffer des D_CODES a des valeurs raisonnables */
    for( count = 0; count < MAX_TOOLS; count++ )
    for( int count = 0; count < MAX_TOOLS; count++ )
    {
        if( m_Aperture_List[count] == NULL )
            continue;

        m_Aperture_List[count]->m_Num_Dcode = count + FIRST_DCODE;
        m_Aperture_List[count]->Clear_D_CODE_Data();
    }
@@ -184,7 +206,6 @@ void GERBER::InitToolTable()
D_CODE::D_CODE( int num_dcode )
{
    m_Num_Dcode = num_dcode;
    m_Macro = 0;
    Clear_D_CODE_Data();
}

@@ -203,6 +224,25 @@ void D_CODE::Clear_D_CODE_Data()
    m_DrillShape = 0;
    m_InUse   = FALSE;
    m_Defined = FALSE;
    m_Macro = 0;
}

const wxChar* D_CODE::ShowApertureType( APERTURE_T aType )
{
    const wxChar* ret;

    switch( aType )
    {
    case APT_CIRCLE:    ret = wxT( "Round" );   break;
    case APT_LINE:      ret = wxT( "Line" );    break;
    case APT_RECT:      ret = wxT( "Rect" );    break;
    case APT_OVAL:      ret = wxT( "Oval" );    break;
    case APT_POLYGON:   ret = wxT( "Poly" );    break;
    case APT_MACRO:     ret = wxT( "Macro" );   break;
    default:            ret = wxT( "???" );     break;
    }

    return ret;
}


@@ -217,7 +257,7 @@ int WinEDA_GerberFrame::Read_D_Code_File( const wxString& D_Code_FullFileName )
    char     c_type_outil[256];
    char     line[GERBER_BUFZ];
    wxString msg;
    D_CODE*  pt_Dcode;
    D_CODE*  dcode;
    FILE*    dest;
    int      layer = GetScreen()->m_Active_Layer;
    int      type_outil;
@@ -227,6 +267,9 @@ int WinEDA_GerberFrame::Read_D_Code_File( const wxString& D_Code_FullFileName )
        g_GERBER_List[layer] = new GERBER( layer );
    }

    GERBER* gerber = g_GERBER_List[layer];


    /* Mise a jour de l'echelle gerber : */
    dcode_scale   = 10; /* ici unit dcode = mil, unit interne = 0.1 mil
                          *  -> 1 unite dcode = 10 unit PCB */
@@ -243,16 +286,18 @@ int WinEDA_GerberFrame::Read_D_Code_File( const wxString& D_Code_FullFileName )
        return -1;
    }

    g_GERBER_List[layer]->InitToolTable();
    gerber->InitToolTable();

    while( fgets( line, sizeof(line) - 1, dest ) != NULL )
    {
        if( *line == ';' )
            continue;                       /* Commentaire */

        if( strlen( line ) < 10 )
            continue;                       /* Probablemant ligne vide */

        pt_Dcode = NULL; current_Dcode = 0;
        dcode = NULL;
        current_Dcode = 0;

        /* Determination du type de fichier D_Code */
        ptcar = line;
@@ -277,7 +322,9 @@ int WinEDA_GerberFrame::Read_D_Code_File( const wxString& D_Code_FullFileName )
        }
        else        /* valeurs en inches a convertir en mils */
        {
            fdrill = 0; current_Dcode = 0; fdrill = 0;
            fdrill = 0;
            current_Dcode = 0;

            sscanf( line, "%f,%f,%1s", &fdimV, &fdimH, c_type_outil );
            ptcar = line;
            while( *ptcar )
@@ -311,12 +358,12 @@ int WinEDA_GerberFrame::Read_D_Code_File( const wxString& D_Code_FullFileName )
        if( current_Dcode >= MAX_TOOLS )
            continue;

        pt_Dcode = ReturnToolDescr( layer, current_Dcode );
        pt_Dcode->m_Size.x  = dimH;
        pt_Dcode->m_Size.y  = dimV;
        pt_Dcode->m_Shape   = (APERTURE_T) type_outil;
        pt_Dcode->m_Drill.x = pt_Dcode->m_Drill.y = drill;
        pt_Dcode->m_Defined = TRUE;
        dcode = gerber->GetDCODE( current_Dcode );
        dcode->m_Size.x  = dimH;
        dcode->m_Size.y  = dimV;
        dcode->m_Shape   = (APERTURE_T) type_outil;
        dcode->m_Drill.x = dcode->m_Drill.y = drill;
        dcode->m_Defined = TRUE;
    }

    fclose( dest );
@@ -332,14 +379,15 @@ void WinEDA_GerberFrame::CopyDCodesSizeToItems()
/* Set Size Items (Lines, Flashes) from DCodes List
 */
{
    TRACK*  track;
    D_CODE* pt_Dcode; /* Pointeur sur le D code*/

    track = m_Pcb->m_Track;
    for( ; track != NULL; track = (TRACK*) track->Pnext )
    for( TRACK* track = m_Pcb->m_Track;  track;  track = track->Next() )
    {
        pt_Dcode = ReturnToolDescr( track->GetLayer(), track->GetNet() );
        pt_Dcode->m_InUse = TRUE;
        GERBER* gerber = g_GERBER_List[track->GetLayer()];
        wxASSERT( gerber );

        D_CODE* dcode  = gerber->GetDCODE( track->GetNet(), false );
        wxASSERT( dcode );

        dcode->m_InUse = TRUE;

        if(                                     // Line Item
            (track->m_Shape == S_SEGMENT )      /* segment rectiligne */
@@ -349,12 +397,12 @@ void WinEDA_GerberFrame::CopyDCodesSizeToItems()
            || (track->m_Shape == S_ARC_RECT )  /* segment en arc de cercle (bouts droits) (GERBER)*/
            )
        {
            track->m_Width = pt_Dcode->m_Size.x;
            track->m_Width = dcode->m_Size.x;
        }
        else        // Spots ( Flashed Items )
        {
            int    width, len;
            wxSize size = pt_Dcode->m_Size;
            wxSize size = dcode->m_Size;

            width = MIN( size.x, size.y );
            len   = MAX( size.x, size.y ) - width;
@@ -365,7 +413,7 @@ void WinEDA_GerberFrame::CopyDCodesSizeToItems()
            track->m_Start.y = (track->m_Start.y + track->m_End.y) / 2;
            track->m_End = track->m_Start;  // m_Start = m_End = Spot center

            switch( pt_Dcode->m_Shape )
            switch( dcode->m_Shape )
            {
            case APT_LINE:          // ne devrait pas etre utilis� ici
            case APT_CIRCLE:        /* spot round (for GERBER)*/
@@ -397,26 +445,6 @@ void WinEDA_GerberFrame::CopyDCodesSizeToItems()
}


/*********************************************************/
D_CODE* ReturnToolDescr( int layer, int Dcode, int* index )
/*********************************************************/
{
    GERBER*     gerber = g_GERBER_List[layer];
    D_CODE*     pt_dcode  = NULL;

    if( index )
        *index = 0;

    if( gerber && Dcode >= FIRST_DCODE && Dcode < MAX_TOOLS )
    {
        pt_dcode = gerber->m_Aperture_List[Dcode - FIRST_DCODE];
        if( index )
            *index = Dcode - FIRST_DCODE + 1;
    }
    return pt_dcode;
}


/************************************************/
void WinEDA_GerberFrame::Liste_D_Codes( wxDC* DC )
/************************************************/
@@ -427,15 +455,13 @@ void WinEDA_GerberFrame::Liste_D_Codes( wxDC* DC )
    WinEDA_TextFrame*   List;
    int                 scale      = 10000;
    int                 curr_layer = GetScreen()->m_Active_Layer;
    int                 layer;
    GERBER*             gerber;

    /* Construction de la liste des messages */
    List = new WinEDA_TextFrame( this, _( "List D codes" ) );

    for( layer = 0; layer < 32; layer++ )
    for( int layer = 0; layer < 32; layer++ )
    {
        gerber = g_GERBER_List[layer];
        GERBER* gerber = g_GERBER_List[layer];
        if( gerber == NULL )
            continue;

@@ -450,7 +476,7 @@ void WinEDA_GerberFrame::Liste_D_Codes( wxDC* DC )

        for( ii = 0, jj = 1; ii < MAX_TOOLS; ii++ )
        {
            pt_D_code = gerber->m_Aperture_List[ii];
            pt_D_code = gerber->GetDCODE( ii + FIRST_DCODE, false );
            if( pt_D_code == NULL )
                continue;

@@ -463,7 +489,8 @@ void WinEDA_GerberFrame::Liste_D_Codes( wxDC* DC )
                pt_D_code->m_Num_Dcode,
                (float) pt_D_code->m_Size.y / scale,
                (float) pt_D_code->m_Size.x / scale,
                g_GERBER_Tool_Type[pt_D_code->m_Shape] );
                D_CODE::ShowApertureType( pt_D_code->m_Shape )
                );

            if( !pt_D_code->m_Defined )
                Line += wxT( " ?" );
+104 −47
Original line number Diff line number Diff line
@@ -58,16 +58,6 @@ enum APERTURE_T
    APT_MACRO = 'M'
};

/* replaced by APERTURE_T
enum Gerb_StandardShape {
    GERB_CIRCLE = 1,
    GERB_RECT,
    GERB_LINE,
    GERB_OVALE,
    GERB_SPECIAL_SHAPE
};
*/


// Interpolation type
enum Gerb_Interpolation {
@@ -111,21 +101,49 @@ enum Gerb_Analyse_Cmd {
    ENTER_RS274X_CMD
};

class D_CODE;


/**
 * Struct DCODE_PARAM
 * Class DCODE_PARAM
 * holds a parameter for a DCODE or an "aperture macro" as defined within standard RS274X.
 * The \a value field can be either a constant or a place holder for a DCODE
 * parameter.
 */
struct DCODE_PARAM
class DCODE_PARAM
{
public:
    DCODE_PARAM() :
        isImmediate(true),
        index(-1),
        value(0.0)
    {}

    bool    isImmediate;    ///< the \a value field is an actual value, not a parameter place holder.
    double  GetValue( const D_CODE* aDcode );
    void SetValue( double aValue )
    {
        value = aValue;
        index = -1;
    }

    /**
     * Function IsImmediate
     * tests if this DCODE_PARAM holds an immediate parameter or is a pointer into
     * a parameter held by an owning D_CODE.
     */
    bool IsImmediate() { return index == -1; }

    int GetIndex()
    {
        return index;
    }

    void SetIndex( int aIndex )
    {
        index = aIndex;
    }

private:
    int     index;      ///< if -1, then \a value field is an immediate value, else this is an index into a D_CODE parameter.
    double  value;      ///< if immediate then the value, else an integer index into D_CODE.m_am_params.
};

@@ -183,7 +201,7 @@ struct APERTURE_MACRO
 */
struct APERTURE_MACRO_less_than
{
    // a "less than" test on two wxStrings
    // a "less than" test on two APERTURE_MACROs (.name wxStrings)
    bool operator()( const APERTURE_MACRO& am1, const APERTURE_MACRO& am2) const
    {
        return am1.name.Cmp( am2.name ) < 0;  // case specific wxString compare
@@ -206,6 +224,14 @@ typedef std::pair<APERTURE_MACRO_SET::iterator, bool> APERTURE_MACRO_SET_PAIR;
 */
class D_CODE
{
    APERTURE_MACRO* m_Macro;    ///< no ownership, points to GERBER.m_aperture_macros element

    /**
     * parameters used only when this D_CODE holds a reference to an aperture
     * macro, and these parameters would customize the macro.
     */
    DCODE_PARAMS   m_am_params;

public:
    wxSize      m_Size;        /* Dimensions horiz et Vert */
    APERTURE_T  m_Shape;       /* shape ( Line, rect , circulaire , ovale .. ) */
@@ -216,27 +242,55 @@ public:
    bool        m_Defined;     /* FALSE si non defini */
    wxString    m_SpecialDescr;

    APERTURE_MACRO* m_Macro;    ///< no ownership, points to GERBER.m_aperture_macros element

    /**
     * parameters used only when this D_CODE holds a reference to an aperture
     * macro, and these parameters would customize the macro.
     */
    DCODE_PARAMS   m_am_params;

public:
    D_CODE( int num_dcode );
    ~D_CODE();
    void Clear_D_CODE_Data();

    void AppendParam( double aValue )
    {
        DCODE_PARAM param;

        param.SetValue( aValue );

        m_am_params.push_back( param );
    }

    void SetMacro( APERTURE_MACRO* aMacro )
    {
        m_Macro = aMacro;
    }

    /**
     * Function ShowApertureType
     * returns a character string telling what type of aperture type \a aType is.
     * @param aType The aperture type to show.
     */
    static const wxChar* ShowApertureType( APERTURE_T aType );
};


inline double DCODE_PARAM::GetValue( const D_CODE* aDcode )
{
    if( IsImmediate() )
        return value;
    else
    {
        // get the parameter from aDcode
        return 0.0;
    }
}


/**
 * Class GERBER
 * holds the data for one gerber file or layer
 */
class GERBER
{
    D_CODE*       m_Aperture_List[MAX_TOOLS];                   ///< Dcode (Aperture) List for this layer


public:
    wxString      m_FileName;                                   // Full File Name for this layer
    wxString      m_Name;                                       // Layer name
@@ -247,7 +301,7 @@ public:
    bool          m_NoTrailingZeros;                            // True: zeros a droite supprims
    bool          m_MirorA;                                     // True: miror / axe A (X)
    bool          m_MirorB;                                     // True: miror / axe B (Y)
    bool          m_As_DCode;                                   // TRUE = DCodes in file (FALSE = no DCode->
    bool          m_Has_DCode;                                  // TRUE = DCodes in file (FALSE = no DCode->
    // separate DCode file
    wxPoint       m_Offset;                                     // Coord Offset
    wxSize        m_FmtScale;                                   // Fmt 2.3: m_FmtScale = 3, fmt 3.4: m_FmtScale = 4
@@ -262,7 +316,6 @@ public:
    wxPoint       m_CurrentPos;                                 // current specified coord for plot
    wxPoint       m_PreviousPos;                                // old current specified coord for plot
    wxPoint       m_IJPos;                                      // IJ coord (for arcs & circles )
    D_CODE*       m_Aperture_List[MAX_TOOLS + FIRST_DCODE + 1]; // Dcode (Aperture) List for this layer

    FILE*         m_Current_File;                               // Current file to read
    FILE*         m_FilesList[12];                              // Files list
@@ -283,6 +336,11 @@ public:
    void    Clear_GERBER();
    int     ReturnUsedDcodeNumber();
    void    ResetDefaultValues();


    /**
     * Function InitToolTable
     */
    void    InitToolTable();

    // Routines utilises en lecture de ficher gerber
@@ -324,36 +382,35 @@ public:
     * @return bool - true if a macro was read in successfully, else false.
     */
    bool    ReadApertureMacro( char aBuff[GERBER_BUFZ], char*& text, FILE* gerber_file );
};



/**************/
/* rs274x.cpp */
/**************/
bool GetEndOfBlock( char buff[GERBER_BUFZ], char*& text, FILE* gerber_file );

    /**
     * Function GetDCODE
     * returns a pointer to the D_CODE within this GERBER for the given
     * \a aDCODE.
     * @param aDCODE The numeric value of the D_CODE to look up.
     * @param createIfNoExist If true, then create the D_CODE if it does not exist.
     * @return D_CODE* - the one implied by the given \a aDCODE, or NULL
     *            if the requested \a aDCODE is out of range.
     */
    D_CODE* GetDCODE( int aDCODE, bool createIfNoExist=true );

    /**
 * Function ReturnToolDescr
 * returns a D_CODE given a global layer index and Dcode value.
 * @param aLayer The index into the global array of GERBER called g_GERBER_List[].
 * @param aDcode The dcode value to look up.
 * @param aIndex If not null, where to put a one basedindex into the GERBER's m_Aperture_List[] array.
 * @return D_CODE* - the looked up D_CODE or NULL if none was encountered in the gerber file for given \a aDcode.
     * Function FindApertureMacro
     * looks up a previously read in aperture macro.
     * @param aLookup A dummy APERTURE_MACRO with [only] the name field set.
     * @return APERTURE_MACRO* - the one with a matching name, or NULL if not found.
     */
D_CODE * ReturnToolDescr( int layer, int Dcode, int * index = NULL );
    APERTURE_MACRO* FindApertureMacro( const APERTURE_MACRO& aLookup );
};


eda_global const wxChar* g_GERBER_Tool_Type[6]
#ifdef MAIN
= {
    wxT( "????" ), wxT( "Round" ), wxT( "Rect" ), wxT( "Line" ), wxT( "Oval" ), wxT( "Macro" )
}

/**************/
/* rs274x.cpp */
/**************/
bool GetEndOfBlock( char buff[GERBER_BUFZ], char*& text, FILE* gerber_file );

#endif
;

eda_global GERBER* g_GERBER_List[32];

+1 −1
Original line number Diff line number Diff line
@@ -261,7 +261,7 @@ bool WinEDA_GerberFrame::Read_GERBER_File( wxDC* DC,
    /* Init  DCodes list and perhaps read a DCODES file,
     * if the gerber file is only a RS274D file (without any aperture information)
     */
    if( !gerber->m_As_DCode )
    if( !gerber->m_Has_DCode )
    {
        wxString DCodeFileName;
        if( D_Code_FullFileName.IsEmpty() )
Loading