From 26736baa9ba460d80d193d63e7c9087e9f5ddb91 Mon Sep 17 00:00:00 2001 From: dickelbeck Date: Sun, 9 Nov 2008 02:57:42 +0000 Subject: [PATCH] gerbview cleanup, and working towards aperture macro support --- change_log.txt | 11 +++ gerbview/affiche.cpp | 61 +------------- gerbview/dcode.cpp | 183 ++++++++++++++++++++++++------------------ gerbview/gerbview.h | 151 +++++++++++++++++++++++----------- gerbview/readgerb.cpp | 2 +- gerbview/rs274x.cpp | 132 ++++++++++++++++++++---------- include/macros.h | 4 + pcbnew/plotgerb.h | 143 +++++++++++++++++---------------- 8 files changed, 392 insertions(+), 295 deletions(-) diff --git a/change_log.txt b/change_log.txt index 1ddb178538..82331f883b 100644 --- a/change_log.txt +++ b/change_log.txt @@ -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 +================================================================================ ++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 ================================================================================ +all: diff --git a/gerbview/affiche.cpp b/gerbview/affiche.cpp index b0170cde31..ae4a9672b5 100644 --- a/gerbview/affiche.cpp +++ b/gerbview/affiche.cpp @@ -31,14 +31,14 @@ void Affiche_Infos_PCB_Texte( WinEDA_BasePcbFrame* frame, TEXTE_PCB* pt_texte ) else Affiche_1_Parametre( frame, 1, _( "PCB Text" ), pt_texte->m_Text, DARKGREEN ); - Line = _( "Layer " ); + Line = _( "Layer " ); Line << pt_texte->GetLayer() + 1; - + Affiche_1_Parametre( frame, 28, _( "Layer:" ), Line, g_DesignSettings.m_LayerColor[pt_texte->GetLayer()] ); Affiche_1_Parametre( frame, 36, _( "Mirror" ), wxEmptyString, GREEN ); - + if( (pt_texte->m_Miroir & 1) ) Affiche_1_Parametre( frame, -1, wxEmptyString, _( "No" ), DARKGREEN ); else @@ -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 ); -} diff --git a/gerbview/dcode.cpp b/gerbview/dcode.cpp index bbacdaf018..60db9d39f6 100644 --- a/gerbview/dcode.cpp +++ b/gerbview/dcode.cpp @@ -63,37 +63,67 @@ 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; - - if( m_Aperture_List ) + for( unsigned ii = 0; ii < DIM(m_Aperture_List); ii++ ) { - for( ii = 0; ii < MAX_TOOLS; ii++ ) - { - delete m_Aperture_List[ii]; - m_Aperture_List[ii] = NULL; - } + delete m_Aperture_List[ii]; + // m_Aperture_List[ii] = NULL; } } +D_CODE* GERBER::GetDCODE( int aDCODE, bool create ) +{ + unsigned ndx = aDCODE - FIRST_DCODE; + + if( ndx < (unsigned) DIM(m_Aperture_List) ) + { + // 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 +} + + /******************************************/ void GERBER::ResetDefaultValues() /******************************************/ @@ -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-> - // separate DCode file + 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( unsigned ii = 0; ii < DIM(m_Aperture_List); ii++ ) { - for( ii = 0; ii < MAX_TOOLS; 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( " ?" ); diff --git a/gerbview/gerbview.h b/gerbview/gerbview.h index 48ef6186e5..8fc2530b1a 100644 --- a/gerbview/gerbview.h +++ b/gerbview/gerbview.h @@ -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,22 +101,50 @@ 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 value; ///< if immediate then the value, else an integer index into D_CODE.m_am_params. + 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_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 supprimés 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 utilisées en lecture de ficher gerber @@ -324,6 +382,26 @@ public: * @return bool - true if a macro was read in successfully, else false. */ bool ReadApertureMacro( char aBuff[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 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. + */ + APERTURE_MACRO* FindApertureMacro( const APERTURE_MACRO& aLookup ); }; @@ -334,27 +412,6 @@ public: bool GetEndOfBlock( char buff[GERBER_BUFZ], char*& text, FILE* gerber_file ); -/** - * 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. - */ -D_CODE * ReturnToolDescr( int layer, int Dcode, int * index = NULL ); - - -eda_global const wxChar* g_GERBER_Tool_Type[6] -#ifdef MAIN -= { - wxT( "????" ), wxT( "Round" ), wxT( "Rect" ), wxT( "Line" ), wxT( "Oval" ), wxT( "Macro" ) -} - - -#endif -; - eda_global GERBER* g_GERBER_List[32]; diff --git a/gerbview/readgerb.cpp b/gerbview/readgerb.cpp index 5878160645..3308410899 100644 --- a/gerbview/readgerb.cpp +++ b/gerbview/readgerb.cpp @@ -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() ) diff --git a/gerbview/rs274x.cpp b/gerbview/rs274x.cpp index c1c19848df..37be0d058e 100644 --- a/gerbview/rs274x.cpp +++ b/gerbview/rs274x.cpp @@ -92,7 +92,7 @@ static int ReadInt( char*& text ) /** * Function ReadDouble - * reads a double in from a character buffer. If there is a comma after the double, + * reads a double from an ASCII character buffer. If there is a comma after the double, * then skip over that. * @param text A reference to a character pointer from which the ASCII double * is read from and the pointer advanced for each character read. @@ -171,9 +171,7 @@ bool GERBER::ExecuteRS274XCommand( int command, char buff[GERBER_BUFZ], char*& t { int code; int xy_seq_len, xy_seq_char; - char ctmp; bool ok = TRUE; - D_CODE* dcode; char line[GERBER_BUFZ]; wxString msg; double fcoord; @@ -221,19 +219,21 @@ bool GERBER::ExecuteRS274XCommand( int command, char buff[GERBER_BUFZ], char*& t case 'X': case 'Y': // Valeurs transmises :2 (really xy_seq_len : FIX ME) digits - code = *(text++); - ctmp = *(text++) - '0'; - if( code == 'X' ) { - m_FmtScale.x = *text - '0'; // = nb chiffres apres la virgule - m_FmtLen.x = ctmp + m_FmtScale.x; // = nb total de chiffres + code = *(text++); + char ctmp = *(text++) - '0'; + if( code == 'X' ) + { + m_FmtScale.x = *text - '0'; // = nb chiffres apres la virgule + m_FmtLen.x = ctmp + m_FmtScale.x; // = nb total de chiffres + } + else + { + m_FmtScale.y = *text - '0'; + m_FmtLen.y = ctmp + m_FmtScale.y; + } + text++; } - else - { - m_FmtScale.y = *text - '0'; - m_FmtLen.y = ctmp + m_FmtScale.y; - } - text++; break; case '*': @@ -321,10 +321,6 @@ bool GERBER::ExecuteRS274XCommand( int command, char buff[GERBER_BUFZ], char*& t m_LayerNegative = FALSE; break; - case AP_MACRO: - ReadApertureMacro( buff, text, m_Current_File ); - break; - case INCLUDE_FILE: if( m_FilesPtr >= 10 ) { @@ -349,29 +345,45 @@ bool GERBER::ExecuteRS274XCommand( int command, char buff[GERBER_BUFZ], char*& t m_FilesPtr++; break; + case AP_MACRO: + ok = ReadApertureMacro( buff, text, m_Current_File ); + if( !ok ) + break; + break; + case AP_DEFINITION: - if( *text != 'D' ) + + // input example: %ADD30R,0.081800X0.101500*% + // at this point, text points to 2nd 'D' + + if( *text++ != 'D' ) { ok = FALSE; break; } - m_As_DCode = TRUE; - text++; + + m_Has_DCode = TRUE; code = ReadInt( text ); - ctmp = *text; - dcode = ReturnToolDescr( m_Layer, code ); + D_CODE* dcode; + dcode = GetDCODE( code ); if( dcode == NULL ) break; - if( text[1] == ',' ) // Tool usuel (C,R,O,P) + // at this point, text points to character after the ADD, i.e. R in example above + + // if text[0] is one of the usual apertures: (C,R,O,P), there is a comma after it. + if( text[1] == ',' ) { - text += 2; // text pointe size ( 1er modifier) + char stdAperture = *text; + + text += 2; // skip "C," for example + dcode->m_Size.x = dcode->m_Size.y = (int) round( ReadDouble( text ) * conv_scale ); - switch( ctmp ) + switch( stdAperture ) { case 'C': // Circle dcode->m_Shape = APT_CIRCLE; @@ -402,7 +414,7 @@ bool GERBER::ExecuteRS274XCommand( int command, char buff[GERBER_BUFZ], char*& t case 'O': // oval case 'R': // rect - dcode->m_Shape = (ctmp == 'O') ? APT_OVAL : APT_RECT; + dcode->m_Shape = (stdAperture == 'O') ? APT_OVAL : APT_RECT; while( *text == ' ' ) text++; @@ -444,6 +456,40 @@ bool GERBER::ExecuteRS274XCommand( int command, char buff[GERBER_BUFZ], char*& t break; } } + + else // text[0] starts an aperture macro name + { + APERTURE_MACRO am_lookup; + + while( *text && *text!='*' && *text!=',' ) + am_lookup.name.Append( *text++ ); + + if( *text && *text==',' ) + { + while( *text && *text!='*' ) + { + double param = ReadDouble( text ); + if( *text == 'X' ) + ++text; + + dcode->AppendParam( param ); + } + } + + // lookup the aperture macro here. + APERTURE_MACRO* pam = FindApertureMacro( am_lookup ); + if( !pam ) + { + // @todo not found, don't know how to report an error + D( printf("aperture macro %s not found\n", CONV_TO_UTF8(am_lookup.name) );) + ok = false; + break; + } + + D(printf("pam has %d parameters\n", pam->primitives.size() );) + + dcode->SetMacro( (APERTURE_MACRO*) pam ); + } break; default: @@ -531,7 +577,6 @@ bool GERBER::ReadApertureMacro( char buff[GERBER_BUFZ], char*& text, FILE* gerbe switch( prim.primitive_id ) { - default: case AMP_CIRCLE: paramCount = 4; break; @@ -558,43 +603,48 @@ bool GERBER::ReadApertureMacro( char buff[GERBER_BUFZ], char*& text, FILE* gerbe case AMP_THERMAL: paramCount = 6; break; + default: + // @todo, there needs to be a way of reporting the line number and character offset. + D(printf("Invalid primitive id code %d\n", prim.primitive_id );) + return false; } - DCODE_PARAM param; - for( int i=0; i= 0 ? (y) : ( -(y) ) ) #endif +/// # of elements in an arrray +#define DIM(x) (sizeof(x)/sizeof((x)[0])) + + #define DEG2RAD( Deg ) ( (Deg) * M_PI / 180.0 ) #define RAD2DEG( Rad ) ( (Rad) * 180.0 / M_PI ) diff --git a/pcbnew/plotgerb.h b/pcbnew/plotgerb.h index 54745f7ab0..b8841647f3 100644 --- a/pcbnew/plotgerb.h +++ b/pcbnew/plotgerb.h @@ -1,6 +1,6 @@ - /************/ - /* pcbplot.h*/ - /************/ + /************/ + /* pcbplot.h*/ + /************/ #ifndef PLOTGERB_H #define PLOTGERB_H @@ -8,81 +8,84 @@ /* Format Gerber : NOTES : Fonctions preparatoires: - Gn = - G01 interpolation lineaire ( trace de droites ) - G02,G20,G21 Interpolation circulaire , sens trigo < 0 - G03,G30,G31 Interpolation circulaire , sens trigo > 0 - G04 commentaire - G06 Interpolation parabolique - G07 Interpolation cubique - G10 interpolation lineaire ( echelle 10x ) - G11 interpolation lineaire ( echelle 0.1x ) - G12 interpolation lineaire ( echelle 0.01x ) - G36 Start polygon description - G37 End polygon description - G52 plot symbole reference par Dnn code - G53 plot symbole reference par Dnn ; symbole tourne de -90 degres - G54 Selection d'outil - G55 Mode exposition photo - G56 plot symbole reference par Dnn A code - G57 affiche le symbole reference sur la console - G58 plot et affiche le symbole reference sur la console - G60 interpolation lineaire ( echelle 100x ) - G70 Unites = Inches - G71 Unites = Millimetres - G74 supprime interpolation circulaire sur 360 degre, revient a G01 - G75 Active interpolation circulaire sur 360 degre - G90 Mode Coordonnees absolues - G91 Mode Coordonnees Relatives + Gn = + G01 interpolation lineaire ( trace de droites ) + G02,G20,G21 Interpolation circulaire , sens trigo < 0 + G03,G30,G31 Interpolation circulaire , sens trigo > 0 + G04 commentaire + G06 Interpolation parabolique + G07 Interpolation cubique + G10 interpolation lineaire ( echelle 10x ) + G11 interpolation lineaire ( echelle 0.1x ) + G12 interpolation lineaire ( echelle 0.01x ) + G36 Start polygon description + G37 End polygon description + G52 plot symbole reference par Dnn code + G53 plot symbole reference par Dnn ; symbole tourne de -90 degres + G54 Selection d'outil + G55 Mode exposition photo + G56 plot symbole reference par Dnn A code + G57 affiche le symbole reference sur la console + G58 plot et affiche le symbole reference sur la console + G60 interpolation lineaire ( echelle 100x ) + G70 Unites = Inches + G71 Unites = Millimetres + G74 supprime interpolation circulaire sur 360 degre, revient a G01 + G75 Active interpolation circulaire sur 360 degre + G90 Mode Coordonnees absolues + G91 Mode Coordonnees Relatives Coordonnees X,Y - X,Y sont suivies de + ou - et de m+n chiffres (non separes) - m = partie entiere - n = partie apres la virgule - formats classiques : m = 2, n = 3 (format 2.3) - m = 3, n = 4 (format 3.4) - ex: - G__ X00345Y-06123 D__* + X,Y sont suivies de + ou - et de m+n chiffres (non separes) + m = partie entiere + n = partie apres la virgule + formats classiques : m = 2, n = 3 (format 2.3) + m = 3, n = 4 (format 3.4) + ex: + G__ X00345Y-06123 D__* Outils et D_CODES - numero d'outil ( identification des formes ) - 1 a 99 (classique) - 1 a 999 - D_CODES: + numero d'outil ( identification des formes ) + 1 a 99 (classique) + 1 a 999 + D_CODES: - D01 ... D9 = codes d'action: - D01 = activation de lumiere ( baisser de plume) - D02 = extinction de lumiere ( lever de plume) - D03 = Flash - D09 = VAPE Flash - D51 = precede par G54 -> Select VAPE + D01 ... D9 = codes d'action: + D01 = activation de lumiere ( baisser de plume) + D02 = extinction de lumiere ( lever de plume) + D03 = Flash + D09 = VAPE Flash + D51 = precede par G54 -> Select VAPE - D10 ... D255 = Indentification d'outils ( d'ouvertures ) - Ne sont pas tj dans l'ordre ( voir tableau ci dessous) + D10 ... D255 = Indentification d'outils ( d'ouvertures ) + Ne sont pas tj dans l'ordre ( voir tableau ci dessous) */ - /*************************************/ - /* Constantes utiles en trace GERBER */ - /*************************************/ + /*************************************/ + /* Constantes utiles en trace GERBER */ + /*************************************/ /* codes de type de forme d'outils */ + +/* #define GERB_CIRCLE 1 #define GERB_RECT 2 #define GERB_LINE 3 #define GERB_OVALE 4 #define GERB_DONUT 5 +*/ /* liste des D_CODES en fonction de leur numero d'ordre (numero d'outil) - (l'ordre 0 n'est pas utilise) ; - Tools have D_CODES >= 10 - D_CODES <= 9 are used for commands only: - D01 ... D9 = command codes for photo plotting: - D01 = Light on - D02 = Light off - D03 = Flash - D04 .. D08 = ? - D09 = VAPE Flash + (l'ordre 0 n'est pas utilise) ; + Tools have D_CODES >= 10 + D_CODES <= 9 are used for commands only: + D01 ... D9 = command codes for photo plotting: + D01 = Light on + D02 = Light off + D03 = Flash + D04 .. D08 = ? + D09 = VAPE Flash */ #define FIRST_DCODE_VALUE 10 @@ -91,17 +94,17 @@ Outils et D_CODES class D_CODE { public: - D_CODE * m_Pnext, * m_Pback; /* for a linked list */ - wxSize m_Size; /* horiz and Vert size*/ - int m_Type; /* Type ( Line, rect , circulaire , ovale .. ); -1 = not used (free) descr */ - int m_NumDcode; /* code number ( >= 10 ); 0 = not in use */ + D_CODE * m_Pnext, * m_Pback; /* for a linked list */ + wxSize m_Size; /* horiz and Vert size*/ + int m_Type; /* Type ( Line, rect , circulaire , ovale .. ); -1 = not used (free) descr */ + int m_NumDcode; /* code number ( >= 10 ); 0 = not in use */ - D_CODE() - { - m_Pnext = m_Pback = NULL; - m_Type = -1; - m_NumDcode = 0; - } + D_CODE() + { + m_Pnext = m_Pback = NULL; + m_Type = -1; + m_NumDcode = 0; + } } ;