diff --git a/gerbview/CMakeLists.txt b/gerbview/CMakeLists.txt index 9df9d51e0a..e119a98b23 100644 --- a/gerbview/CMakeLists.txt +++ b/gerbview/CMakeLists.txt @@ -23,6 +23,7 @@ set(DIALOGS_SRCS set(GERBVIEW_SRCS block.cpp + class_am_param.cpp class_aperture_macro.cpp class_GERBER.cpp class_gerber_draw_item.cpp diff --git a/gerbview/class_am_param.cpp b/gerbview/class_am_param.cpp new file mode 100644 index 0000000000..23c3015fe2 --- /dev/null +++ b/gerbview/class_am_param.cpp @@ -0,0 +1,98 @@ +/*****************/ +/* am_param.cpp */ +/*****************/ + +/* + * This program source code file is part of KICAD, a free EDA CAD application. + * + * Copyright (C) 1992-2010 Jean-Pierre Charras + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "class_am_param.h" + +extern int ReadInt( char*& text, bool aSkipSeparator = true ); +extern double ReadDouble( char*& text, bool aSkipSeparator = true ); + +/*Class AM_PARAM + * holds a parameter for an "aperture macro" as defined within + * standard RS274X. The \a value field can be a constant, i.e. "immediate" + * parameter or it may not be used if this param is going to defer to the + * referencing aperture macro. In that case, the \a index field is an index + * into the aperture macro's parameters. + */ + +double AM_PARAM::GetValue( const D_CODE* aDcode ) const +{ + if( IsImmediate() ) + return value; + else + { + // the first one was numbered 1, not zero, as in $1, see page 19 of spec. + unsigned ndx = GetIndex(); + wxASSERT( aDcode ); + + // get the parameter from the aDcode + if( ndx <= aDcode->GetParamCount() ) + return aDcode->GetParam( ndx ); + else + { + wxASSERT( GetIndex() <= aDcode->GetParamCount() ); + return 0.0; + } + } +} + +/** + * Function ReadParam + * Read one aperture macro parameter + * a parameter can be: + * a number + * a reference to an aperture definition parameter value: $1 ot $3 ... + * a parameter definition can be complex and have operators between numbers and/or other parameter + * like $1+3 or $2x2.. + * Parameters are separated by a comma ( of finish by *) + * @param aText = pointer to the parameter to read. Will be modified to point to the next field + * @return true if a param is read, or false + */ +bool AM_PARAM::ReadParam( char*& aText ) +{ + bool found = false; + if( *aText == '$' ) // value defined later, in aperture description + { + ++aText; + SetIndex( ReadInt( aText, false ) ); + found = true; + } + else + { + SetValue( ReadDouble( aText, false ) ); + found = true; + } + + // Skip extra characters and separator + while( *aText && (*aText != ',') && (*aText != '*') ) + aText++; + if( *aText == ',' ) + aText++; + + return found; +} diff --git a/gerbview/class_am_param.h b/gerbview/class_am_param.h new file mode 100644 index 0000000000..303c5334fc --- /dev/null +++ b/gerbview/class_am_param.h @@ -0,0 +1,174 @@ +/*****************/ +/* am_param.h */ +/*****************/ + +/* + * This program source code file is part of KICAD, a free EDA CAD application. + * + * Copyright (C) 1992-2010 Jean-Pierre Charras + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _AM_PARAM_H_ +#define _AM_PARAM_H_ + +/* +An aperture macro defines a complex shape and is a list of aperture primitives. +Each aperture primitive defines a simple shape (circle, rect, regular polygon...) +Inside a given aperture primitive, a fixed list of parameters defines info +about the shape: size, thickness, number of vertex ... + +Each parameter can be an immediate value or a defered value. +When value is defered, it is defined when the aperture macro is instancied by +an ADD macro command + +Actual values of a parmeter can also be the result of an arithmetic operation. + +Here is some examples: +An immediate value: +3.5 +A deferend value: +$2 means: replace me by the second value given in the ADD command +Actual value as arithmetic calculation: +$2/2+1 + +Note also a defered parameter can be defined in aperture macro, +but outside aperture primitives. Example +%AMRECTHERM* +$4=$3/2* parameter $4 is half value of parameter $3 +21,1,$1-$3,$2-$3,0-$1/2-$4,0-$2/2-$4,0* +For the aperture primitive, parameters $1 to $3 will be defined in ADD command, +and $4 is defined inside the macro + +Some examples of aperture macro definition +A simple definition, no parameters: +%AMMOIRE10* +6,0,0,0.350000,0.005,0.050,3,0.005,0.400000,0.0*% +Example of instanciation: +%ADD19THERM19*% + +A simple definition, one parameter: +%AMCIRCLE* +1,1,$1,0,0* +Example of instanciation: +%ADD11CIRCLE,.5*% + +A definition, with parameters and arithmetic operations: +%AMVECTOR* +2,1,$1,0,0,$2+1,$3,-135*% +Example of instanciation: +%ADD12VECTOR,0.05X0X0*% + +A more complicated aperture macro definition, with parameters and arihmetic operations: +%AMRNDREC* +0 this is a comment* +21,1,$1+$1,$2+$2-$3-$3,0,0,0* +21,1,$1+$1-$3-$3,$2+$2,0,0,0* +1,1,$3+$3,$1-$3,$2-$3* +1,1,$3+$3,$3-$1,$2-$3* +1,1,$3+$3,$1-$3,$3-$2* +1,1,$3+$3,$3-$1,$3-$2*% +Example of instanciation: + +A more complicated sample of aperture macro definition: +G04 Rectangular Thermal Macro, params: W/2, H/2, T/2 * +%AMRECTHERM* +$4=$3/2* +21,1,$1-$3,$2-$3,0-$1/2-$4,0-$2/2-$4,0* +21,1,$1-$3,$2-$3,0-$1/2-$4,$2/2+$4,0* +21,1,$1-$3,$2-$3,$1/2+$4,0-$2/2-$4,0* +21,1,$1-$3,$2-$3,$1/2+$4,$2/2+$4,0*% +Example of instanciation: +%ADD28RECTHERM,0.035591X0.041496X0.005000*% +*/ + +#include + +#include "dcode.h" + +/** + * Class AM_PARAM + * holds a parameter for an "aperture macro" as defined within + * standard RS274X. The \a value field can be a constant, i.e. "immediate" + * parameter or it may not be used if this param is going to defer to the + * referencing aperture macro. In that case, the \a index field is an index + * into the aperture macro's parameters. + */ +class AM_PARAM +{ +public: + AM_PARAM() : + index( -1 ), + value( 0.0 ) + {} + + double GetValue( const D_CODE* aDcode ) const; + + void SetValue( double aValue ) + { + value = aValue; + index = -1; + } + + + /** + * Function IsImmediate + * tests if this AM_PARAM holds an immediate parameter or is a pointer + * into a parameter held by an owning D_CODE. + */ + bool IsImmediate() const { return index == -1; } + + unsigned GetIndex() const + { + return (unsigned) index; + } + + + void SetIndex( int aIndex ) + { + index = aIndex; + } + + /** + * Function ReadParam + * Read one aperture macro parameter + * a parameter can be: + * a number + * a reference to an aperture definition parameter value: $1 ot $3 ... + * a parameter definition can be complex and have operators between numbers and/or other parameter + * like $1+3 or $2x2.. + * Parameters are separated by a comma ( of finish by *) + * @param aText = pointer to the parameter to read. Will be modified to point to the next field + * @return true if a param is read, or false + */ + bool ReadParam( char*& aText ); + +private: + int index; ///< if -1, then \a value field is an immediate value, + // else this is an index into parent's + // D_CODE.m_am_params. + double value; ///< if IsImmediate()==true then use the value, else + // not used. +}; + +typedef std::vector AM_PARAMS; + +#endif // _AM_PARAM_H_ diff --git a/gerbview/class_aperture_macro.h b/gerbview/class_aperture_macro.h index 45547b81ec..752c6ba276 100644 --- a/gerbview/class_aperture_macro.h +++ b/gerbview/class_aperture_macro.h @@ -34,6 +34,7 @@ #include #include "base_struct.h" +#include "class_am_param.h" /** @@ -68,7 +69,7 @@ class AM_PRIMITIVE { public: AM_PRIMITIVE_ID primitive_id; ///< The primitive type - DCODE_PARAMS params; ///< A sequence of parameters used by + AM_PARAMS params; ///< A sequence of parameters used by // the primitive bool m_GerbMetric; // units for this primitive: // false = Inches, true = metric diff --git a/gerbview/dcode.h b/gerbview/dcode.h index e80e9baf7d..01b0c6fd84 100644 --- a/gerbview/dcode.h +++ b/gerbview/dcode.h @@ -31,7 +31,7 @@ #define _DCODE_H_ #include -#include +//#include #include "base_struct.h" class GERBER_DRAW_ITEM; @@ -67,62 +67,6 @@ enum APERTURE_DEF_HOLETYPE { #define TOOLS_MAX_COUNT (LAST_DCODE + 1) class APERTURE_MACRO; -class D_CODE; - - -/** - * Class DCODE_PARAM - * holds a parameter for a DCODE or an "aperture macro" as defined within - * standard RS274X. The \a value field can be a constant, i.e. "immediate" - * parameter or it may not be used if this param is going to defer to the - * referencing aperture macro. In that case, the \a index field is an index - * into the aperture macro's parameters. - */ -class DCODE_PARAM -{ -public: - DCODE_PARAM() : - index( -1 ), - value( 0.0 ) - {} - - double GetValue( const D_CODE* aDcode ) const; - - 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() const { return index == -1; } - - unsigned GetIndex() const - { - return (unsigned) 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 parent's - // D_CODE.m_am_params. - double value; ///< if IsImmediate()==true then use the value, else - // not used. -}; - -typedef std::vector DCODE_PARAMS; /** @@ -131,16 +75,14 @@ typedef std::vector DCODE_PARAMS; */ class D_CODE { - friend class DCODE_PARAM; - +private: 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; + std::vector m_am_params; std::vector m_PolyCorners; /* Polygon used to draw APT_POLYGON shape and some other * complex shapes which are converted to polygon @@ -164,13 +106,37 @@ public: ~D_CODE(); void Clear_D_CODE_Data(); + /** + * AppendParam() + * Add a parameter to the D_CODE parameter list. + * used to customize the corresponding aperture macro + */ void AppendParam( double aValue ) { - DCODE_PARAM param; + m_am_params.push_back( aValue ); + } - param.SetValue( aValue ); + /** + * GetParamCount() + * Returns the number of parameters stored in parameter list. + */ + unsigned GetParamCount() const + { + return m_am_params.size(); + } - m_am_params.push_back( param ); + /** + * GetParam() + * Returns a parameter stored in parameter list. + * @param aIdx = index of parameter + */ + double GetParam( unsigned aIdx ) const + { + wxASSERT( aIdx <= m_am_params.size() ); + if( aIdx <= m_am_params.size() ) + return m_am_params[aIdx - 1]; + else + return 0; } @@ -245,26 +211,4 @@ public: }; -inline double DCODE_PARAM::GetValue( const D_CODE* aDcode ) const -{ - if( IsImmediate() ) - return value; - else - { - // the first one was numbered 1, not zero, as in $1, see page 19 of spec. - unsigned ndx = GetIndex() - 1; - wxASSERT( aDcode ); - - // get the parameter from the aDcode - if( ndx < aDcode->m_am_params.size() ) - return aDcode->m_am_params[ndx].GetValue( NULL ); - else - { - wxASSERT( GetIndex() - 1 < aDcode->m_am_params.size() ); - return 0.0; - } - } -} - - #endif // ifndef _DCODE_H_ diff --git a/gerbview/rs274_read_XY_and_IJ_coordinates.cpp b/gerbview/rs274_read_XY_and_IJ_coordinates.cpp index 8a20ec8ef5..76ed0822d7 100644 --- a/gerbview/rs274_read_XY_and_IJ_coordinates.cpp +++ b/gerbview/rs274_read_XY_and_IJ_coordinates.cpp @@ -201,3 +201,48 @@ wxPoint GERBER_IMAGE::ReadIJCoord( char*& Text ) m_IJPos = pos; return pos; } + + +// Helper functions: + +/** + * Function ReadInt + * reads an int from an ASCII character buffer. If there is a comma after the + * int, then skip over that. + * @param text A reference to a character pointer from which bytes are read + * and the pointer is advanced for each byte read. + * @param aSkipSeparator = true (default) to skip comma + * @return int - The int read in. + */ +int ReadInt( char*& text, bool aSkipSeparator = true ) +{ + int ret = (int) strtol( text, &text, 10 ); + + if( *text == ',' || isspace( *text ) ) + if( aSkipSeparator ) + ++text; + + return ret; +} + + +/** + * Function ReadDouble + * 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. + * @param aSkipSeparator = true (default) to skip comma + * @return double + */ +double ReadDouble( char*& text, bool aSkipSeparator = true ) +{ + double ret = strtod( text, &text ); + + if( *text == ',' || isspace( *text ) ) + if( aSkipSeparator ) + ++text; + + return ret; +} + diff --git a/gerbview/rs274x.cpp b/gerbview/rs274x.cpp index b3e56657be..63b61d663e 100644 --- a/gerbview/rs274x.cpp +++ b/gerbview/rs274x.cpp @@ -5,14 +5,14 @@ #include "fctsys.h" #include "common.h" -//#include "macros.h" #include "gerbview.h" #include "class_GERBER.h" -#define CODE( x, y ) ( ( (x) << 8 ) + (y) ) +extern int ReadInt( char*& text, bool aSkipSeparator = true ); +extern double ReadDouble( char*& text, bool aSkipSeparator = true ); -// Helper function to read a primitive macro param (TODO: make it DCODE_PARAM function) -static bool ReadMacroParam( DCODE_PARAM& aParam, char*& aText ); + +#define CODE( x, y ) ( ( (x) << 8 ) + (y) ) // See rs274xrevd_e.pdf, table 1: RS-274X parameters order of entry // in gerber files, when a coordinate is given (like X78Y600 or I0J80): @@ -92,48 +92,6 @@ static int ReadXCommand( char*& text ) } -/** - * Function ReadInt - * reads an int from an ASCII character buffer. If there is a comma after the - * int, then skip over that. - * @param text A reference to a character pointer from which bytes are read - * and the pointer is advanced for each byte read. - * @param aSkipSeparator = true (default) to skip comma - * @return int - The int read in. - */ -static int ReadInt( char*& text, bool aSkipSeparator = true ) -{ - int ret = (int) strtol( text, &text, 10 ); - - if( *text == ',' || isspace( *text ) ) - if( aSkipSeparator ) - ++text; - - return ret; -} - - -/** - * Function ReadDouble - * 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. - * @param aSkipSeparator = true (default) to skip comma - * @return double - */ -static double ReadDouble( char*& text, bool aSkipSeparator = true ) -{ - double ret = strtod( text, &text ); - - if( *text == ',' || isspace( *text ) ) - if( aSkipSeparator ) - ++text; - - return ret; -} - - bool GERBER_IMAGE::ReadRS274XCommand( char buff[GERBER_BUFZ], char*& text ) { bool ok = true; @@ -952,14 +910,14 @@ bool GERBER_IMAGE::ReadApertureMacro( char buff[GERBER_BUFZ], int i; for( i = 0; i < paramCount && *text && *text != '*'; ++i ) { - prim.params.push_back( DCODE_PARAM() ); + prim.params.push_back( AM_PARAM() ); - DCODE_PARAM& param = prim.params.back(); + AM_PARAM& param = prim.params.back(); text = GetNextLine( buff, text, gerber_file ); if( text == NULL) // End of File return false; - ReadMacroParam( param, text ); + param.ReadParam( text ); } if( i < paramCount ) @@ -984,14 +942,14 @@ bool GERBER_IMAGE::ReadApertureMacro( char buff[GERBER_BUFZ], for( int i = 0; i < paramCount && *text != '*'; ++i ) { - prim.params.push_back( DCODE_PARAM() ); + prim.params.push_back( AM_PARAM() ); - DCODE_PARAM& param = prim.params.back(); + AM_PARAM& param = prim.params.back(); text = GetNextLine( buff, text, gerber_file ); if( text == NULL ) // End of File return false; - ReadMacroParam( param, text ); + param.ReadParam( text ); } } @@ -1003,37 +961,3 @@ bool GERBER_IMAGE::ReadApertureMacro( char buff[GERBER_BUFZ], return true; } -/** - * Function ReadMacroParam - * Read one aperture macro parameter - * a parameter can be: - * a number - * a reference to an aperture definition parameter value: $1 ot $3 ... - * a parameter definition can be complex and have operators between numbers and/or other parameter - * like $1+3 or $2x2.. - * Parameters are separated by a comma ( of finish by *) - * Return if a param is read, or false - */ -static bool ReadMacroParam( DCODE_PARAM& aParam, char*& aText ) -{ - bool found = false; - if( *aText == '$' ) // value defined later, in aperture description - { - ++aText; - aParam.SetIndex( ReadInt( aText, false ) ); - found = true; - } - else - { - aParam.SetValue( ReadDouble( aText, false ) ); - found = true; - } - - // Skip extra characters and separator - while( *aText && (*aText != ',') && (*aText != '*') ) - aText++; - if( *aText == ',' ) - aText++; - - return found; -}