Loading CHANGELOG.txt +14 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,20 @@ KiCad ChangeLog 2010 Please add newer entries at the top, list the date and your name with email address. 2010-dec-01, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr> ================================================================================ Gerbview: Added support for complex definitions of parameters in aperture macros and primitives macro (a complex definition in a parameter that is calculated by an arithmetical expression) Gerbview should now have a decent support of Gerber language. Currently only the obscure knockout command is not supported (I have no motivation to do that) Other "bug": scale in A and B axis is poorly supported: coordinates are scaled, but shapes can have problem: fro instance, a circle is drawn as a circle when A and B scales are different, and perhaps should be an ellipse. On the other hand, Gerber doc is not clear about the meaning of A and B scale. (Alas! Gerber doc is not clear about most of advanced commands) 2010-nov-19 UPDATE Wayne Stambaugh <stambaughw@verizon.net> ================================================================================ ++EESchema Loading gerbview/class_am_param.cpp +176 −34 Original line number Diff line number Diff line Loading @@ -28,39 +28,126 @@ */ #include "class_am_param.h" #include "class_aperture_macro.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. * holds a parameter value for an "aperture macro" as defined within * standard RS274X. The parameter can be a constant, i.e. "immediate" parameter, * or depend on some defered values, defined in a D_CODE, by the ADD command. * Note the actual value could need an evaluation from an arithmetical expression * items in the expression are stored in . * A simple definition is just a value stored in one item in m_paramStack */ AM_PARAM::AM_PARAM( ) { m_index = -1; } /** * Function IsImmediate * tests if this AM_PARAM holds an immediate parameter or has parameter * held by an owning D_CODE. */ bool AM_PARAM::IsImmediate() const { bool isimmediate = true; for( unsigned ii = 0; ii < m_paramStack.size(); ii++ ) { if( m_paramStack[ii].IsDefered() ) { // a defered value is found in operand list, // so the parameter is not immediate isimmediate = false; break; } } return isimmediate; } double AM_PARAM::GetValue( const D_CODE* aDcode ) const { if( IsImmediate() ) return value; else double paramvalue = 0.0; double curr_value = 0.0; parm_item_type state = POPVALUE; for( unsigned ii = 0; ii < m_paramStack.size(); ii++ ) { AM_PARAM_ITEM item = m_paramStack[ii]; switch( item.GetType() ) { // the first one was numbered 1, not zero, as in $1, see page 19 of spec. unsigned ndx = GetIndex(); wxASSERT( aDcode ); case ADD: case SUB: case MUL: case DIV: // just an operator for next parameter value: store it state = item.GetType(); break; case PUSHPARM: // get the parameter from the aDcode if( ndx <= aDcode->GetParamCount() ) return aDcode->GetParam( ndx ); else if( aDcode && item.GetIndex() <= aDcode->GetParamCount() ) curr_value = aDcode->GetParam( item.GetIndex() ); else // Get parameter from local param definition { wxASSERT( GetIndex() <= aDcode->GetParamCount() ); return 0.0; const APERTURE_MACRO * am_parent = aDcode->GetMacro(); curr_value = am_parent->GetLocalParam( aDcode, item.GetIndex() ); } // Fall through case PUSHVALUE: // a value is on the stack: if( item.GetType() == PUSHVALUE ) curr_value = item.GetValue(); switch( state ) { case POPVALUE: paramvalue = curr_value; break; case ADD: paramvalue += curr_value; break; case SUB: paramvalue -= curr_value; break; case MUL: paramvalue *= curr_value; break; case DIV: paramvalue /= curr_value; break; default: wxLogDebug( wxT( "AM_PARAM::GetValue() : unexpected operator\n" ) ); break; } break; default: wxLogDebug( wxT( "AM_PARAM::GetValue(): unexpected type\n" ) ); break; } } return paramvalue; } /** * add an operator/operand to the current stack * aType = NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, EQUATE * aValue required only for PUSHVALUE (double) or PUSHPARM (int) aType. */ void AM_PARAM::PushOperator( parm_item_type aType, double aValue ) { AM_PARAM_ITEM item( aType, aValue); m_paramStack.push_back( item ); } void AM_PARAM::PushOperator( parm_item_type aType, int aValue ) { AM_PARAM_ITEM item( aType, aValue); m_paramStack.push_back( item ); } /** * Function ReadParam Loading @@ -70,6 +157,7 @@ double AM_PARAM::GetValue( const D_CODE* aDcode ) const * 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.. * Note minus sign is not always an operator. It can be the sign of a value. * 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 Loading @@ -77,25 +165,79 @@ double AM_PARAM::GetValue( const D_CODE* aDcode ) const bool AM_PARAM::ReadParam( char*& aText ) { bool found = false; int ivalue; double dvalue; bool end = false; if( *aText == '$' ) // value defined later, in aperture description while( !end ) { switch( *aText ) { case ',': aText++; // fall through case 0: // EOL case '*': // Terminator in a gerber command end = true; break; case ' ': aText++; break; case '$': // defered value defined later, in ADD command which define defered parameters ++aText; SetIndex( ReadInt( aText, false ) ); ivalue = ReadInt( aText, false ); if( m_index < 1 ) SetIndex( ivalue ); PushOperator( PUSHPARM, ivalue ); found = true; break; case '/': PushOperator( DIV ); aText++; break; case 'x': case 'X': PushOperator( MUL ); aText++; break; case '-': case '+': // Test if this is an operator between 2 params, or the sign of a value if( m_paramStack.size() > 0 && !m_paramStack.back().IsOperator() ) { // Seems an operator PushOperator( *aText == '+' ? ADD : SUB ); aText++; } else { SetValue( ReadDouble( aText, false ) ); { // seems the sign of a value dvalue = ReadDouble( aText, false ); PushOperator( PUSHVALUE, dvalue ); found = true; } break; // Skip extra characters and separator while( *aText && (*aText != ',') && (*aText != '*') ) case '=': // A local definition found like $4=$3/2 // At this point, one defered parameter is expected to be read. // this parameter value (the index) is stored in m_index. // The list of items is cleared aText++; m_paramStack.clear(); found = false; break; if( *aText == ',' ) aText++; default: dvalue = ReadDouble( aText, false ); PushOperator( PUSHVALUE, dvalue ); found = true; break; } } return found; } gerbview/class_am_param.h +115 −21 Original line number Diff line number Diff line Loading @@ -103,50 +103,151 @@ #include <vector> #include "dcode.h" /* Values of a parameter can be the result of an arithmetic operation, between immediate values and defered value. From an idea found in Gerbv, here is the way to evaluate a parameter. a AM_PARAM_ITEM holds info about operands and operators in a parameter definition ( a AM_PARAM ) like $2+$2-$3-$3/2 There is no precedence defined in gerber RS274X, so actual value is calculated step to step. Parameter definition is described by a very primitive assembler. This "program "should describe how to calculate the parameter. The assembler consist of 8 instruction intended for a stackbased machine. The instructions are: NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, EQUATE The instructions ---------------- NOP : The no operation. This is the default instruction and are added as a security measure. PUSHVALUE : Pushes an arithmetical value on the stack. This machine only works with floats on the stack. PUSHPARM: Pushes a defered parameter onto the stack. Gerber aperture macros accepts parameters to be set when later declared, so the same macro can be used at several instances. Which parameter to be set is an integer and starts with 1. definition is like $1 or $3 ADD : The mathematical operation +. Takes the two uppermost values on the the stack, adds them and pushes the result back onto the stack. SUB : Same as ADD, but with -. MUL : Same as ADD, but with *. DIV : Same as ADD, but with /. POPVALUE : used when evaluate the expression: store current calculated value */ enum parm_item_type { NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, POPVALUE }; /** * Class AM_PARAM * holds a parameter for an "aperture macro" as defined within * holds an operand for an AM_PARAM 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 class AM_PARAM_ITEM { public: AM_PARAM() : index( -1 ), value( 0.0 ) {} private: parm_item_type m_type; // the type of item double m_dvalue; // the value, for PUSHVALUE type item int m_ivalue; // the integer value, for PUSHPARM type item double GetValue( const D_CODE* aDcode ) const; public: AM_PARAM_ITEM( parm_item_type aType = NOP, double aValue = 0.0) { m_type = aType; m_dvalue = aValue; m_ivalue = 0; } AM_PARAM_ITEM( parm_item_type aType = NOP, int aValue = 0) { m_type = aType; m_dvalue = 0.0; m_ivalue = aValue; } void SetValue( double aValue ) { value = aValue; index = -1; m_dvalue = aValue; } double GetValue( ) const { return m_dvalue; } parm_item_type GetType() const { return m_type; } unsigned GetIndex() const { return (unsigned) m_ivalue; } bool IsOperator() const { return m_type == ADD || m_type == SUB || m_type == MUL || m_type == DIV; } bool IsOperand() const { return m_type == PUSHVALUE || m_type == PUSHPARM; } bool IsDefered() const { return m_type == PUSHPARM; } }; /** * Class AM_PARAM * holds a parameter value for an "aperture macro" as defined within * standard RS274X. The parameter can be a constant, i.e. "immediate" parameter, * or depend on some defered values, defined in a D_CODE, by the ADD command. * Note the actual value could need an evaluation from an arithmetical expression * items in the expression are stored in . * A simple definition is just a value stored in one item in m_paramStack */ class AM_PARAM { private: int m_index; // has meaning to define parameter local to an aperture macro std::vector<AM_PARAM_ITEM> m_paramStack; // list of operands/operators to evalutate the actual value // if a par def is $3/2, there are 3 items in stack: // 3 (type PUSHPARM) , / (type DIV), 2 (type PUSHVALUE) public: AM_PARAM(); /** * function PushOperator * add an operator/operand to the current stack * @param aType = the type of item (NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, EQUATE) * @param aValue = the item value, double for PUSHVALUE or int for PUSHPARM type. */ void PushOperator( parm_item_type aType, double aValue ); void PushOperator( parm_item_type aType, int aValue = 0); double GetValue( const D_CODE* aDcode ) const; /** * Function IsImmediate * tests if this AM_PARAM holds an immediate parameter or is a pointer * into a parameter held by an owning D_CODE. * @return true if the value is immediate, i.e. no defered value in operands used in its definition */ bool IsImmediate() const { return index == -1; } bool IsImmediate() const; unsigned GetIndex() const { return (unsigned) index; return (unsigned) m_index; } void SetIndex( int aIndex ) { index = aIndex; m_index = aIndex; } /** * Function ReadParam * Read one aperture macro parameter Loading @@ -160,13 +261,6 @@ public: AM_PARAM() : * @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_PARAM> AM_PARAMS; Loading gerbview/class_aperture_macro.cpp +30 −1 Original line number Diff line number Diff line Loading @@ -56,7 +56,6 @@ static wxPoint mapPt( double x, double y, bool isMetric ) return ret; } /** * Function mapExposure * translates the first parameter from an aperture macro into a current Loading Loading @@ -762,3 +761,33 @@ int APERTURE_MACRO::GetShapeDim( GERBER_DRAW_ITEM* aParent ) return dim; } /** * function GetLocalParam * Usually, parameters are defined inside the aperture primitive * using immediate mode or defered mode. * in defered mode the value is defined in a DCODE that want to use the aperture macro. * But some parameters are defined outside the aperture primitive * and are local to the aperture macro * @return the value of a defered parameter defined inside the aperture macro * @param aParamId = the param id (defined by $3 or $5 ..) to evaluate */ double APERTURE_MACRO::GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const { // find parameter descr. const AM_PARAM * param = NULL; for( unsigned ii = 0; ii < m_localparamStack.size(); ii ++ ) { if( m_localparamStack[ii].GetIndex() == aParamId ) { param = &m_localparamStack[ii]; break; } } if ( param == NULL ) // not found return 0.0; // Evaluate parameter double value = param->GetValue( aDcode ); return value; } gerbview/class_aperture_macro.h +27 −1 Original line number Diff line number Diff line Loading @@ -45,6 +45,13 @@ * 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 * 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 */ /** Loading Loading @@ -83,7 +90,6 @@ public: // the primitive bool m_GerbMetric; // units for this primitive: // false = Inches, true = metric public: AM_PRIMITIVE( bool aGerbMetric, AM_PRIMITIVE_ID aId = AMP_UNKNOWN ) { primitive_id = aId; Loading Loading @@ -167,6 +173,26 @@ struct APERTURE_MACRO wxString name; ///< The name of the aperture macro AM_PRIMITIVES primitives; ///< A sequence of AM_PRIMITIVEs /* 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 * m_localparamStack handle a list of local defered parameters */ AM_PARAMS m_localparamStack; /** * function GetLocalParam * Usually, parameters are defined inside the aperture primitive * using immediate mode or defered mode. * in defered mode the value is defined in a DCODE that want to use the aperture macro. * But some parameters are defined outside the aperture primitive * and are local to the aperture macro * @return the value of a defered parameter defined inside the aperture macro * @param aParamId = the param id (defined by $3 or $5 ..) to evaluate */ double GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const; /** * Function DrawApertureMacroShape * Draw the primitive shape for flashed items. Loading Loading
CHANGELOG.txt +14 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,20 @@ KiCad ChangeLog 2010 Please add newer entries at the top, list the date and your name with email address. 2010-dec-01, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr> ================================================================================ Gerbview: Added support for complex definitions of parameters in aperture macros and primitives macro (a complex definition in a parameter that is calculated by an arithmetical expression) Gerbview should now have a decent support of Gerber language. Currently only the obscure knockout command is not supported (I have no motivation to do that) Other "bug": scale in A and B axis is poorly supported: coordinates are scaled, but shapes can have problem: fro instance, a circle is drawn as a circle when A and B scales are different, and perhaps should be an ellipse. On the other hand, Gerber doc is not clear about the meaning of A and B scale. (Alas! Gerber doc is not clear about most of advanced commands) 2010-nov-19 UPDATE Wayne Stambaugh <stambaughw@verizon.net> ================================================================================ ++EESchema Loading
gerbview/class_am_param.cpp +176 −34 Original line number Diff line number Diff line Loading @@ -28,39 +28,126 @@ */ #include "class_am_param.h" #include "class_aperture_macro.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. * holds a parameter value for an "aperture macro" as defined within * standard RS274X. The parameter can be a constant, i.e. "immediate" parameter, * or depend on some defered values, defined in a D_CODE, by the ADD command. * Note the actual value could need an evaluation from an arithmetical expression * items in the expression are stored in . * A simple definition is just a value stored in one item in m_paramStack */ AM_PARAM::AM_PARAM( ) { m_index = -1; } /** * Function IsImmediate * tests if this AM_PARAM holds an immediate parameter or has parameter * held by an owning D_CODE. */ bool AM_PARAM::IsImmediate() const { bool isimmediate = true; for( unsigned ii = 0; ii < m_paramStack.size(); ii++ ) { if( m_paramStack[ii].IsDefered() ) { // a defered value is found in operand list, // so the parameter is not immediate isimmediate = false; break; } } return isimmediate; } double AM_PARAM::GetValue( const D_CODE* aDcode ) const { if( IsImmediate() ) return value; else double paramvalue = 0.0; double curr_value = 0.0; parm_item_type state = POPVALUE; for( unsigned ii = 0; ii < m_paramStack.size(); ii++ ) { AM_PARAM_ITEM item = m_paramStack[ii]; switch( item.GetType() ) { // the first one was numbered 1, not zero, as in $1, see page 19 of spec. unsigned ndx = GetIndex(); wxASSERT( aDcode ); case ADD: case SUB: case MUL: case DIV: // just an operator for next parameter value: store it state = item.GetType(); break; case PUSHPARM: // get the parameter from the aDcode if( ndx <= aDcode->GetParamCount() ) return aDcode->GetParam( ndx ); else if( aDcode && item.GetIndex() <= aDcode->GetParamCount() ) curr_value = aDcode->GetParam( item.GetIndex() ); else // Get parameter from local param definition { wxASSERT( GetIndex() <= aDcode->GetParamCount() ); return 0.0; const APERTURE_MACRO * am_parent = aDcode->GetMacro(); curr_value = am_parent->GetLocalParam( aDcode, item.GetIndex() ); } // Fall through case PUSHVALUE: // a value is on the stack: if( item.GetType() == PUSHVALUE ) curr_value = item.GetValue(); switch( state ) { case POPVALUE: paramvalue = curr_value; break; case ADD: paramvalue += curr_value; break; case SUB: paramvalue -= curr_value; break; case MUL: paramvalue *= curr_value; break; case DIV: paramvalue /= curr_value; break; default: wxLogDebug( wxT( "AM_PARAM::GetValue() : unexpected operator\n" ) ); break; } break; default: wxLogDebug( wxT( "AM_PARAM::GetValue(): unexpected type\n" ) ); break; } } return paramvalue; } /** * add an operator/operand to the current stack * aType = NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, EQUATE * aValue required only for PUSHVALUE (double) or PUSHPARM (int) aType. */ void AM_PARAM::PushOperator( parm_item_type aType, double aValue ) { AM_PARAM_ITEM item( aType, aValue); m_paramStack.push_back( item ); } void AM_PARAM::PushOperator( parm_item_type aType, int aValue ) { AM_PARAM_ITEM item( aType, aValue); m_paramStack.push_back( item ); } /** * Function ReadParam Loading @@ -70,6 +157,7 @@ double AM_PARAM::GetValue( const D_CODE* aDcode ) const * 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.. * Note minus sign is not always an operator. It can be the sign of a value. * 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 Loading @@ -77,25 +165,79 @@ double AM_PARAM::GetValue( const D_CODE* aDcode ) const bool AM_PARAM::ReadParam( char*& aText ) { bool found = false; int ivalue; double dvalue; bool end = false; if( *aText == '$' ) // value defined later, in aperture description while( !end ) { switch( *aText ) { case ',': aText++; // fall through case 0: // EOL case '*': // Terminator in a gerber command end = true; break; case ' ': aText++; break; case '$': // defered value defined later, in ADD command which define defered parameters ++aText; SetIndex( ReadInt( aText, false ) ); ivalue = ReadInt( aText, false ); if( m_index < 1 ) SetIndex( ivalue ); PushOperator( PUSHPARM, ivalue ); found = true; break; case '/': PushOperator( DIV ); aText++; break; case 'x': case 'X': PushOperator( MUL ); aText++; break; case '-': case '+': // Test if this is an operator between 2 params, or the sign of a value if( m_paramStack.size() > 0 && !m_paramStack.back().IsOperator() ) { // Seems an operator PushOperator( *aText == '+' ? ADD : SUB ); aText++; } else { SetValue( ReadDouble( aText, false ) ); { // seems the sign of a value dvalue = ReadDouble( aText, false ); PushOperator( PUSHVALUE, dvalue ); found = true; } break; // Skip extra characters and separator while( *aText && (*aText != ',') && (*aText != '*') ) case '=': // A local definition found like $4=$3/2 // At this point, one defered parameter is expected to be read. // this parameter value (the index) is stored in m_index. // The list of items is cleared aText++; m_paramStack.clear(); found = false; break; if( *aText == ',' ) aText++; default: dvalue = ReadDouble( aText, false ); PushOperator( PUSHVALUE, dvalue ); found = true; break; } } return found; }
gerbview/class_am_param.h +115 −21 Original line number Diff line number Diff line Loading @@ -103,50 +103,151 @@ #include <vector> #include "dcode.h" /* Values of a parameter can be the result of an arithmetic operation, between immediate values and defered value. From an idea found in Gerbv, here is the way to evaluate a parameter. a AM_PARAM_ITEM holds info about operands and operators in a parameter definition ( a AM_PARAM ) like $2+$2-$3-$3/2 There is no precedence defined in gerber RS274X, so actual value is calculated step to step. Parameter definition is described by a very primitive assembler. This "program "should describe how to calculate the parameter. The assembler consist of 8 instruction intended for a stackbased machine. The instructions are: NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, EQUATE The instructions ---------------- NOP : The no operation. This is the default instruction and are added as a security measure. PUSHVALUE : Pushes an arithmetical value on the stack. This machine only works with floats on the stack. PUSHPARM: Pushes a defered parameter onto the stack. Gerber aperture macros accepts parameters to be set when later declared, so the same macro can be used at several instances. Which parameter to be set is an integer and starts with 1. definition is like $1 or $3 ADD : The mathematical operation +. Takes the two uppermost values on the the stack, adds them and pushes the result back onto the stack. SUB : Same as ADD, but with -. MUL : Same as ADD, but with *. DIV : Same as ADD, but with /. POPVALUE : used when evaluate the expression: store current calculated value */ enum parm_item_type { NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, POPVALUE }; /** * Class AM_PARAM * holds a parameter for an "aperture macro" as defined within * holds an operand for an AM_PARAM 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 class AM_PARAM_ITEM { public: AM_PARAM() : index( -1 ), value( 0.0 ) {} private: parm_item_type m_type; // the type of item double m_dvalue; // the value, for PUSHVALUE type item int m_ivalue; // the integer value, for PUSHPARM type item double GetValue( const D_CODE* aDcode ) const; public: AM_PARAM_ITEM( parm_item_type aType = NOP, double aValue = 0.0) { m_type = aType; m_dvalue = aValue; m_ivalue = 0; } AM_PARAM_ITEM( parm_item_type aType = NOP, int aValue = 0) { m_type = aType; m_dvalue = 0.0; m_ivalue = aValue; } void SetValue( double aValue ) { value = aValue; index = -1; m_dvalue = aValue; } double GetValue( ) const { return m_dvalue; } parm_item_type GetType() const { return m_type; } unsigned GetIndex() const { return (unsigned) m_ivalue; } bool IsOperator() const { return m_type == ADD || m_type == SUB || m_type == MUL || m_type == DIV; } bool IsOperand() const { return m_type == PUSHVALUE || m_type == PUSHPARM; } bool IsDefered() const { return m_type == PUSHPARM; } }; /** * Class AM_PARAM * holds a parameter value for an "aperture macro" as defined within * standard RS274X. The parameter can be a constant, i.e. "immediate" parameter, * or depend on some defered values, defined in a D_CODE, by the ADD command. * Note the actual value could need an evaluation from an arithmetical expression * items in the expression are stored in . * A simple definition is just a value stored in one item in m_paramStack */ class AM_PARAM { private: int m_index; // has meaning to define parameter local to an aperture macro std::vector<AM_PARAM_ITEM> m_paramStack; // list of operands/operators to evalutate the actual value // if a par def is $3/2, there are 3 items in stack: // 3 (type PUSHPARM) , / (type DIV), 2 (type PUSHVALUE) public: AM_PARAM(); /** * function PushOperator * add an operator/operand to the current stack * @param aType = the type of item (NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, EQUATE) * @param aValue = the item value, double for PUSHVALUE or int for PUSHPARM type. */ void PushOperator( parm_item_type aType, double aValue ); void PushOperator( parm_item_type aType, int aValue = 0); double GetValue( const D_CODE* aDcode ) const; /** * Function IsImmediate * tests if this AM_PARAM holds an immediate parameter or is a pointer * into a parameter held by an owning D_CODE. * @return true if the value is immediate, i.e. no defered value in operands used in its definition */ bool IsImmediate() const { return index == -1; } bool IsImmediate() const; unsigned GetIndex() const { return (unsigned) index; return (unsigned) m_index; } void SetIndex( int aIndex ) { index = aIndex; m_index = aIndex; } /** * Function ReadParam * Read one aperture macro parameter Loading @@ -160,13 +261,6 @@ public: AM_PARAM() : * @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_PARAM> AM_PARAMS; Loading
gerbview/class_aperture_macro.cpp +30 −1 Original line number Diff line number Diff line Loading @@ -56,7 +56,6 @@ static wxPoint mapPt( double x, double y, bool isMetric ) return ret; } /** * Function mapExposure * translates the first parameter from an aperture macro into a current Loading Loading @@ -762,3 +761,33 @@ int APERTURE_MACRO::GetShapeDim( GERBER_DRAW_ITEM* aParent ) return dim; } /** * function GetLocalParam * Usually, parameters are defined inside the aperture primitive * using immediate mode or defered mode. * in defered mode the value is defined in a DCODE that want to use the aperture macro. * But some parameters are defined outside the aperture primitive * and are local to the aperture macro * @return the value of a defered parameter defined inside the aperture macro * @param aParamId = the param id (defined by $3 or $5 ..) to evaluate */ double APERTURE_MACRO::GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const { // find parameter descr. const AM_PARAM * param = NULL; for( unsigned ii = 0; ii < m_localparamStack.size(); ii ++ ) { if( m_localparamStack[ii].GetIndex() == aParamId ) { param = &m_localparamStack[ii]; break; } } if ( param == NULL ) // not found return 0.0; // Evaluate parameter double value = param->GetValue( aDcode ); return value; }
gerbview/class_aperture_macro.h +27 −1 Original line number Diff line number Diff line Loading @@ -45,6 +45,13 @@ * 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 * 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 */ /** Loading Loading @@ -83,7 +90,6 @@ public: // the primitive bool m_GerbMetric; // units for this primitive: // false = Inches, true = metric public: AM_PRIMITIVE( bool aGerbMetric, AM_PRIMITIVE_ID aId = AMP_UNKNOWN ) { primitive_id = aId; Loading Loading @@ -167,6 +173,26 @@ struct APERTURE_MACRO wxString name; ///< The name of the aperture macro AM_PRIMITIVES primitives; ///< A sequence of AM_PRIMITIVEs /* 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 * m_localparamStack handle a list of local defered parameters */ AM_PARAMS m_localparamStack; /** * function GetLocalParam * Usually, parameters are defined inside the aperture primitive * using immediate mode or defered mode. * in defered mode the value is defined in a DCODE that want to use the aperture macro. * But some parameters are defined outside the aperture primitive * and are local to the aperture macro * @return the value of a defered parameter defined inside the aperture macro * @param aParamId = the param id (defined by $3 or $5 ..) to evaluate */ double GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const; /** * Function DrawApertureMacroShape * Draw the primitive shape for flashed items. Loading