Commit 26736baa authored by dickelbeck's avatar dickelbeck

gerbview cleanup, and working towards aperture macro support

parent eac91489
......@@ -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:
......
......@@ -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 );
}
This diff is collapsed.
......@@ -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::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,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];
......
......@@ -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() )
......
......@@ -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
}
else
{
m_FmtScale.y = *text - '0';
m_FmtLen.y = ctmp + m_FmtScale.y;
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++;
}
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<num>, 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<paramCount && *text && *text!='*'; ++i )
{
DCODE_PARAM param; // construct it on each loop iteration
if( *text == '$' )
{
++text;
param.isImmediate = false;
param.SetIndex( ReadInt( text ) );
}
else
{
param.isImmediate = true;
}
param.SetValue( ReadDouble( text ) );
param.value = ReadDouble( text );
prim.params.push_back( param );
}
// there are more parameters to read if this is an AMP_OUTLINE
if( prim.primitive_id == AMP_OUTLINE )
{
paramCount = (int) prim.params[1].value * 2 + 1;
// params[1] is a count of polygon points, so it must be given
// in advance, i.e. be immediate.
wxASSERT( prim.params[1].IsImmediate() );
paramCount = (int) prim.params[1].GetValue(0) * 2 + 1;
for( int i=0; i<paramCount && *text && *text!='*'; ++i )
{
DCODE_PARAM param; // construct it on each loop
if( *text == '$' )
{
++text;
param.isImmediate = false;
param.SetIndex( ReadInt( text ) );
}
else
{
param.isImmediate = true;
}
param.SetValue( ReadDouble( text ) );
param.value = ReadDouble( text );
prim.params.push_back( param );
}
}
......
......@@ -25,6 +25,10 @@
#define ABS( y ) ( (y) >= 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 )
......
/************/
/* 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:
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)
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
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 = NULL;
m_Type = -1;
m_NumDcode = 0;
}
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;
}
} ;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment