more free specctra work
This commit is contained in:
parent
7878ba2726
commit
67ebe29b60
|
@ -1,5 +1,4 @@
|
||||||
|
|
||||||
|
|
||||||
Change Log for Kicad
|
Change Log for Kicad
|
||||||
Started 2007-June-11
|
Started 2007-June-11
|
||||||
|
|
||||||
|
@ -16,7 +15,6 @@ email address.
|
||||||
the new track takes the width of the existing track
|
the new track takes the width of the existing track
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
2008-Jan-27 UPDATE Dick Hollenbeck <dick@softplc.com>
|
2008-Jan-27 UPDATE Dick Hollenbeck <dick@softplc.com>
|
||||||
================================================================================
|
================================================================================
|
||||||
+all:
|
+all:
|
||||||
|
|
|
@ -55,6 +55,8 @@
|
||||||
#include <wx/ffile.h>
|
#include <wx/ffile.h>
|
||||||
|
|
||||||
|
|
||||||
|
// To build the DSN beautifier and unit tester, simply uncomment this and then
|
||||||
|
// use CMake's makefile to build target "specctra_test".
|
||||||
//#define STANDALONE // define "stand alone, i.e. unit testing"
|
//#define STANDALONE // define "stand alone, i.e. unit testing"
|
||||||
|
|
||||||
|
|
||||||
|
@ -861,24 +863,32 @@ void SPECCTRA_DB::doWINDOW( WINDOW* growth ) throw( IOError )
|
||||||
switch( tok )
|
switch( tok )
|
||||||
{
|
{
|
||||||
case T_rect:
|
case T_rect:
|
||||||
growth->rectangle = new RECTANGLE( growth );
|
if( growth->shape )
|
||||||
doRECTANGLE( growth->rectangle );
|
unexpected( tok );
|
||||||
|
growth->shape = new RECTANGLE( growth );
|
||||||
|
doRECTANGLE( (RECTANGLE*) growth->shape );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_circle:
|
case T_circle:
|
||||||
growth->circle = new CIRCLE( growth );
|
if( growth->shape )
|
||||||
doCIRCLE( growth->circle );
|
unexpected( tok );
|
||||||
|
growth->shape = new CIRCLE( growth );
|
||||||
|
doCIRCLE( (CIRCLE*) growth->shape );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_path:
|
case T_path:
|
||||||
case T_polygon:
|
case T_polygon:
|
||||||
growth->path = new PATH( growth, tok );
|
if( growth->shape )
|
||||||
doPATH( growth->path );
|
unexpected( tok );
|
||||||
|
growth->shape = new PATH( growth, tok );
|
||||||
|
doPATH( (PATH*) growth->shape );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_qarc:
|
case T_qarc:
|
||||||
growth->qarc = new QARC( growth );
|
if( growth->shape )
|
||||||
doQARC( growth->qarc );
|
unexpected( tok );
|
||||||
|
growth->shape = new QARC( growth );
|
||||||
|
doQARC( (QARC*) growth->shape );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -3353,18 +3363,19 @@ int SPECCTRA_DB::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// factor out a common GetQuoteChar
|
||||||
|
|
||||||
const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee )
|
const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote_char )
|
||||||
{
|
{
|
||||||
// I include '#' so a symbol is not confused with a comment. We intend
|
// I include '#' so a symbol is not confused with a comment. We intend
|
||||||
// to wrap any symbol starting with a '#'.
|
// to wrap any symbol starting with a '#'.
|
||||||
// Our LEXER class handles comments, and comments appear to be an extension
|
// Our LEXER class handles comments, and comments appear to be an extension
|
||||||
// to the SPECCTRA DSN specification.
|
// to the SPECCTRA DSN specification.
|
||||||
if( *wrapee == '#' )
|
if( *wrapee == '#' )
|
||||||
return quote_char.c_str();
|
return quote_char;
|
||||||
|
|
||||||
if( strlen(wrapee)==0 )
|
if( strlen(wrapee)==0 )
|
||||||
return quote_char.c_str();
|
return quote_char;
|
||||||
|
|
||||||
bool isNumber = true;
|
bool isNumber = true;
|
||||||
|
|
||||||
|
@ -3373,19 +3384,25 @@ const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee )
|
||||||
// if the string to be wrapped (wrapee) has a delimiter in it,
|
// if the string to be wrapped (wrapee) has a delimiter in it,
|
||||||
// return the quote_char so caller wraps the wrapee.
|
// return the quote_char so caller wraps the wrapee.
|
||||||
if( strchr( "\t ()", *wrapee ) )
|
if( strchr( "\t ()", *wrapee ) )
|
||||||
return quote_char.c_str();
|
return quote_char;
|
||||||
|
|
||||||
if( !strchr( "01234567890.-+", *wrapee ) )
|
if( !strchr( "01234567890.-+", *wrapee ) )
|
||||||
isNumber = false;
|
isNumber = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( isNumber )
|
if( isNumber )
|
||||||
return quote_char.c_str();
|
return quote_char;
|
||||||
|
|
||||||
return ""; // can use an unwrapped string.
|
return ""; // can use an unwrapped string.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee )
|
||||||
|
{
|
||||||
|
return OUTPUTFORMATTER::GetQuoteChar( wrapee, quote_char.c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SPECCTRA_DB::ExportPCB( wxString filename, bool aNameChange ) throw( IOError )
|
void SPECCTRA_DB::ExportPCB( wxString filename, bool aNameChange ) throw( IOError )
|
||||||
{
|
{
|
||||||
fp = wxFopen( filename, wxT("w") );
|
fp = wxFopen( filename, wxT("w") );
|
||||||
|
@ -3438,6 +3455,8 @@ PCB* SPECCTRA_DB::MakePCB()
|
||||||
|
|
||||||
pcb->structure = new STRUCTURE( pcb );
|
pcb->structure = new STRUCTURE( pcb );
|
||||||
pcb->structure->boundary = new BOUNDARY( pcb->structure );
|
pcb->structure->boundary = new BOUNDARY( pcb->structure );
|
||||||
|
pcb->structure->via = new VIA( pcb->structure );
|
||||||
|
pcb->structure->rules = new RULE( pcb->structure, T_rule );
|
||||||
|
|
||||||
pcb->placement = new PLACEMENT( pcb );
|
pcb->placement = new PLACEMENT( pcb );
|
||||||
|
|
||||||
|
@ -3451,6 +3470,87 @@ PCB* SPECCTRA_DB::MakePCB()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----<STRINGFORMATTER>----------------------------------------------------
|
||||||
|
|
||||||
|
const char* STRINGFORMATTER::GetQuoteChar( const char* wrapee )
|
||||||
|
{
|
||||||
|
// for what we are using STRINGFORMATTER for at this time, we can return the nul string
|
||||||
|
// always.
|
||||||
|
|
||||||
|
return "";
|
||||||
|
// return OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, "\"" );
|
||||||
|
}
|
||||||
|
|
||||||
|
int STRINGFORMATTER::vprint( const char* fmt, va_list ap )
|
||||||
|
{
|
||||||
|
int ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
|
||||||
|
if( ret >= (int) buffer.size() )
|
||||||
|
{
|
||||||
|
buffer.reserve( ret+200 );
|
||||||
|
ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ret > 0 )
|
||||||
|
mystring.append( (const char*) &buffer[0] );
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int STRINGFORMATTER::sprint( const char* fmt, ... )
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start( args, fmt );
|
||||||
|
int ret = vprint( fmt, args);
|
||||||
|
va_end( args );
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int STRINGFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start( args, fmt );
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
int total = 0;
|
||||||
|
|
||||||
|
for( int i=0; i<nestLevel; ++i )
|
||||||
|
{
|
||||||
|
result = sprint( "%*c", NESTWIDTH, ' ' );
|
||||||
|
if( result < 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
total += result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( result<0 || (result=vprint( fmt, args ))<0 )
|
||||||
|
{
|
||||||
|
throw IOError( _("Error writing to STRINGFORMATTER") );
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end( args );
|
||||||
|
|
||||||
|
total += result;
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void STRINGFORMATTER::StripUseless()
|
||||||
|
{
|
||||||
|
for( std::string::iterator i=mystring.begin(); i!=mystring.end(); )
|
||||||
|
{
|
||||||
|
if( isspace( *i ) || *i==')' || *i=='(' )
|
||||||
|
mystring.erase(i);
|
||||||
|
else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----<ELEM>---------------------------------------------------------------
|
//-----<ELEM>---------------------------------------------------------------
|
||||||
|
|
||||||
ELEM::ELEM( DSN_T aType, ELEM* aParent ) :
|
ELEM::ELEM( DSN_T aType, ELEM* aParent ) :
|
||||||
|
@ -3500,8 +3600,40 @@ int ELEM_HOLDER::FindElem( DSN_T aType, int instanceNum )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----<PARSER>-----------------------------------------------------------
|
//-----<PADSTACK>---------------------------------------------------------
|
||||||
|
|
||||||
|
int PADSTACK::Compare( PADSTACK* lhs, PADSTACK* rhs )
|
||||||
|
{
|
||||||
|
if( !lhs->hash.size() )
|
||||||
|
lhs->hash = lhs->makeHash();
|
||||||
|
|
||||||
|
if( !rhs->hash.size() )
|
||||||
|
rhs->hash = rhs->makeHash();
|
||||||
|
|
||||||
|
int result = lhs->hash.compare( rhs->hash );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----<IMAGE>------------------------------------------------------------
|
||||||
|
|
||||||
|
int IMAGE::Compare( IMAGE* lhs, IMAGE* rhs )
|
||||||
|
{
|
||||||
|
if( !lhs->hash.size() )
|
||||||
|
lhs->hash = lhs->makeHash();
|
||||||
|
|
||||||
|
if( !rhs->hash.size() )
|
||||||
|
rhs->hash = rhs->makeHash();
|
||||||
|
|
||||||
|
int result = lhs->hash.compare( rhs->hash );
|
||||||
|
|
||||||
|
// printf("\"%s\" \"%s\" ret=%d\n", lhs->hash.c_str(), rhs->hash.c_str(), result );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----<PARSER>-----------------------------------------------------------
|
||||||
|
|
||||||
PARSER::PARSER( ELEM* aParent ) :
|
PARSER::PARSER( ELEM* aParent ) :
|
||||||
ELEM( T_parser, aParent )
|
ELEM( T_parser, aParent )
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include "fctsys.h"
|
#include "fctsys.h"
|
||||||
#include "dsn.h"
|
#include "dsn.h"
|
||||||
|
|
||||||
|
class TYPE_COLLECTOR; // outside the DSN namespace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,9 +103,86 @@ public:
|
||||||
* if the wrapee does not need to be wrapped.
|
* if the wrapee does not need to be wrapped.
|
||||||
*/
|
*/
|
||||||
virtual const char* GetQuoteChar( const char* wrapee ) = 0;
|
virtual const char* GetQuoteChar( const char* wrapee ) = 0;
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
virtual ~OUTPUTFORMATTER() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetQuoteChar
|
||||||
|
* factor may be used by derived classes to perform quote character selection.
|
||||||
|
* @param wrapee A string that might need wrapping on each end.
|
||||||
|
* @param quote_char A single character C string which hold the current quote character.
|
||||||
|
* @return const char* - the quote_char as a single character string, or ""
|
||||||
|
* if the wrapee does not need to be wrapped.
|
||||||
|
*/
|
||||||
|
static const char* GetQuoteChar( const char* wrapee, const char* quote_char );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class STRINGFORMATTER
|
||||||
|
* implements OUTPUTFORMATTER to a memory buffer. After Print()ing the
|
||||||
|
* string is available through GetString()
|
||||||
|
*/
|
||||||
|
class STRINGFORMATTER : public OUTPUTFORMATTER
|
||||||
|
{
|
||||||
|
std::vector<char> buffer;
|
||||||
|
std::string mystring;
|
||||||
|
|
||||||
|
int sprint( const char* fmt, ... );
|
||||||
|
int vprint( const char* fmt, va_list ap );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor STRINGFORMATTER
|
||||||
|
* reserves space in the buffer
|
||||||
|
*/
|
||||||
|
STRINGFORMATTER( int aReserve = 300 ) :
|
||||||
|
buffer( aReserve, '\0' )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Clear
|
||||||
|
* clears the buffer and empties the internal string.
|
||||||
|
*/
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
mystring.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function StripUseless
|
||||||
|
* removes whitespace, '(', and ')' from the mystring.
|
||||||
|
*/
|
||||||
|
void StripUseless();
|
||||||
|
|
||||||
|
/*
|
||||||
|
const char* c_str()
|
||||||
|
{
|
||||||
|
return mystring.c_str();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::string GetString()
|
||||||
|
{
|
||||||
|
return mystring;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----<OUTPUTFORMATTER>------------------------------------------------
|
||||||
|
int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError );
|
||||||
|
const char* GetQuoteChar( const char* wrapee );
|
||||||
|
//-----</OUTPUTFORMATTER>-----------------------------------------------
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class POINT
|
||||||
|
* is a holder for a point in the SPECCTRA DSN coordinate system. It can also
|
||||||
|
* be used to hold a distance (vector really) from some origin.
|
||||||
|
*/
|
||||||
struct POINT
|
struct POINT
|
||||||
{
|
{
|
||||||
double x;
|
double x;
|
||||||
|
@ -136,14 +215,23 @@ struct POINT
|
||||||
POINT& operator=( const POINT& other )
|
POINT& operator=( const POINT& other )
|
||||||
{
|
{
|
||||||
x = other.x;
|
x = other.x;
|
||||||
if( x == -0.0 ) // correct -0.0 so output looks nice.
|
|
||||||
x = 0.0;
|
|
||||||
y = other.y;
|
y = other.y;
|
||||||
if( y == -0.0 )
|
|
||||||
y = 0.0;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function FixNegativeZero
|
||||||
|
* will change negative zero to positive zero in the IEEE floating point
|
||||||
|
* storage format. Basically turns off the sign bit if the mantiss and exponent
|
||||||
|
* would say the value is zero.
|
||||||
|
*/
|
||||||
|
void FixNegativeZero()
|
||||||
|
{
|
||||||
|
if( x == -0.0 )
|
||||||
|
x = 0.0;
|
||||||
|
if( y == -0.0 )
|
||||||
|
y = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Format
|
* Function Format
|
||||||
|
@ -196,10 +284,33 @@ typedef std::vector<PROPERTY> PROPERTIES;
|
||||||
class ELEM
|
class ELEM
|
||||||
{
|
{
|
||||||
friend class SPECCTRA_DB;
|
friend class SPECCTRA_DB;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DSN_T type;
|
DSN_T type;
|
||||||
ELEM* parent;
|
ELEM* parent;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function makeHash
|
||||||
|
* returns a string which uniquely represents this ELEM amoung other
|
||||||
|
* ELEMs of the same derived class as "this" one.
|
||||||
|
* It is not useable for all derived classes, only those which plan for
|
||||||
|
* it by implementing a FormatContents() function that captures all info
|
||||||
|
* which will be used in the subsequent string compare. THIS SHOULD
|
||||||
|
* NORMALLY EXCLUDE THE TYPENAME, AND INSTANCE NAME OR ID AS WELL.
|
||||||
|
*/
|
||||||
|
std::string makeHash()
|
||||||
|
{
|
||||||
|
STRINGFORMATTER sf;
|
||||||
|
|
||||||
|
FormatContents( &sf, 0 );
|
||||||
|
sf.StripUseless();
|
||||||
|
|
||||||
|
return sf.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -207,7 +318,7 @@ public:
|
||||||
|
|
||||||
virtual ~ELEM();
|
virtual ~ELEM();
|
||||||
|
|
||||||
DSN_T Type() { return type; }
|
DSN_T Type() const { return type; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -216,7 +327,7 @@ public:
|
||||||
* to check for section specific overrides.
|
* to check for section specific overrides.
|
||||||
* @return DSN_T - one of the allowed values to <unit_descriptor>
|
* @return DSN_T - one of the allowed values to <unit_descriptor>
|
||||||
*/
|
*/
|
||||||
virtual DSN_T GetUnits()
|
virtual DSN_T GetUnits() const
|
||||||
{
|
{
|
||||||
if( parent )
|
if( parent )
|
||||||
return parent->GetUnits();
|
return parent->GetUnits();
|
||||||
|
@ -324,14 +435,14 @@ public:
|
||||||
kids.insert( kids.begin()+aIndex, aElem );
|
kids.insert( kids.begin()+aIndex, aElem );
|
||||||
}
|
}
|
||||||
|
|
||||||
ELEM* At( int aIndex )
|
ELEM* At( int aIndex ) const
|
||||||
{
|
{
|
||||||
// we have varying sized objects and are using polymorphism, so we
|
// we have varying sized objects and are using polymorphism, so we
|
||||||
// must return a pointer not a reference.
|
// must return a pointer not a reference.
|
||||||
return &kids[aIndex];
|
return (ELEM*) &kids[aIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
ELEM* operator[]( int aIndex )
|
ELEM* operator[]( int aIndex ) const
|
||||||
{
|
{
|
||||||
return At( aIndex );
|
return At( aIndex );
|
||||||
}
|
}
|
||||||
|
@ -408,7 +519,7 @@ public:
|
||||||
LEXER::GetTokenText(units), value );
|
LEXER::GetTokenText(units), value );
|
||||||
}
|
}
|
||||||
|
|
||||||
DSN_T GetUnits()
|
DSN_T GetUnits() const
|
||||||
{
|
{
|
||||||
return units;
|
return units;
|
||||||
}
|
}
|
||||||
|
@ -439,7 +550,10 @@ public:
|
||||||
void SetCorners( const POINT& aPoint0, const POINT& aPoint1 )
|
void SetCorners( const POINT& aPoint0, const POINT& aPoint1 )
|
||||||
{
|
{
|
||||||
point0 = aPoint0;
|
point0 = aPoint0;
|
||||||
|
point0.FixNegativeZero();
|
||||||
|
|
||||||
point1 = aPoint1;
|
point1 = aPoint1;
|
||||||
|
point1.FixNegativeZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
|
@ -581,7 +695,6 @@ public:
|
||||||
out->Print( nestLevel, ")\n" );
|
out->Print( nestLevel, ")\n" );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef boost::ptr_vector<LAYER_RULE> LAYER_RULES;
|
typedef boost::ptr_vector<LAYER_RULE> LAYER_RULES;
|
||||||
|
|
||||||
|
|
||||||
|
@ -780,15 +893,21 @@ public:
|
||||||
}
|
}
|
||||||
void SetStart( const POINT& aStart )
|
void SetStart( const POINT& aStart )
|
||||||
{
|
{
|
||||||
vertex[0] = aStart;
|
vertex[0] = aStart;
|
||||||
|
// no -0.0 on the printouts!
|
||||||
|
vertex[0].FixNegativeZero();
|
||||||
}
|
}
|
||||||
void SetEnd( const POINT& aEnd )
|
void SetEnd( const POINT& aEnd )
|
||||||
{
|
{
|
||||||
vertex[1] = aEnd;
|
vertex[1] = aEnd;
|
||||||
|
// no -0.0 on the printouts!
|
||||||
|
vertex[1].FixNegativeZero();
|
||||||
}
|
}
|
||||||
void SetCenter( const POINT& aCenter )
|
void SetCenter( const POINT& aCenter )
|
||||||
{
|
{
|
||||||
vertex[2] = aCenter;
|
vertex[2] = aCenter;
|
||||||
|
// no -0.0 on the printouts!
|
||||||
|
vertex[2].FixNegativeZero();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -797,49 +916,53 @@ class WINDOW : public ELEM
|
||||||
{
|
{
|
||||||
friend class SPECCTRA_DB;
|
friend class SPECCTRA_DB;
|
||||||
|
|
||||||
//----- only one of these is used, like a union -----
|
protected:
|
||||||
|
/* shape holds one of these
|
||||||
PATH* path; ///< used for both path and polygon
|
PATH* path; ///< used for both path and polygon
|
||||||
RECTANGLE* rectangle;
|
RECTANGLE* rectangle;
|
||||||
CIRCLE* circle;
|
CIRCLE* circle;
|
||||||
QARC* qarc;
|
QARC* qarc;
|
||||||
//---------------------------------------------------
|
*/
|
||||||
|
ELEM* shape;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WINDOW( ELEM* aParent ) :
|
WINDOW( ELEM* aParent, DSN_T aType = T_window ) :
|
||||||
ELEM( T_window, aParent )
|
ELEM( aType, aParent )
|
||||||
{
|
{
|
||||||
path = 0;
|
shape = 0;
|
||||||
rectangle = 0;
|
|
||||||
circle = 0;
|
|
||||||
qarc = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~WINDOW()
|
~WINDOW()
|
||||||
{
|
{
|
||||||
delete path;
|
delete shape;
|
||||||
delete rectangle;
|
|
||||||
delete circle;
|
|
||||||
delete qarc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
|
||||||
{
|
|
||||||
// these are mutually exclusive
|
|
||||||
if( rectangle )
|
|
||||||
rectangle->Format( out, nestLevel );
|
|
||||||
|
|
||||||
else if( path )
|
|
||||||
path->Format( out, nestLevel );
|
|
||||||
|
|
||||||
else if( circle )
|
|
||||||
circle->Format( out, nestLevel );
|
|
||||||
|
|
||||||
else if( qarc )
|
void SetShape( ELEM* aShape )
|
||||||
qarc->Format( out, nestLevel );
|
{
|
||||||
|
delete shape;
|
||||||
|
shape = aShape;
|
||||||
|
|
||||||
|
if( aShape )
|
||||||
|
{
|
||||||
|
wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle
|
||||||
|
|| aShape->Type()==T_qarc || aShape->Type()==T_path
|
||||||
|
|| aShape->Type()==T_polygon);
|
||||||
|
|
||||||
|
aShape->SetParent( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
|
{
|
||||||
|
out->Print( nestLevel, "(%s ", LEXER::GetTokenText( Type() ) );
|
||||||
|
|
||||||
|
if( shape )
|
||||||
|
shape->Format( out, 0 );
|
||||||
|
|
||||||
|
out->Print( 0, ")\n" );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef boost::ptr_vector<WINDOW> WINDOWS;
|
typedef boost::ptr_vector<WINDOW> WINDOWS;
|
||||||
|
|
||||||
|
|
||||||
|
@ -956,6 +1079,11 @@ public:
|
||||||
ELEM( T_via, aParent )
|
ELEM( T_via, aParent )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppendVia( const char* aViaName )
|
||||||
|
{
|
||||||
|
padstacks.push_back( aViaName );
|
||||||
|
}
|
||||||
|
|
||||||
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
{
|
{
|
||||||
|
@ -1217,13 +1345,13 @@ public:
|
||||||
layer_weight );
|
layer_weight );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
typedef boost::ptr_vector<LAYER_PAIR> LAYER_PAIRS;
|
||||||
|
|
||||||
|
|
||||||
class LAYER_NOISE_WEIGHT : public ELEM
|
class LAYER_NOISE_WEIGHT : public ELEM
|
||||||
{
|
{
|
||||||
friend class SPECCTRA_DB;
|
friend class SPECCTRA_DB;
|
||||||
|
|
||||||
typedef boost::ptr_vector<LAYER_PAIR> LAYER_PAIRS;
|
|
||||||
LAYER_PAIRS layer_pairs;
|
LAYER_PAIRS layer_pairs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1542,7 +1670,7 @@ public:
|
||||||
i->Format( out, nestLevel );
|
i->Format( out, nestLevel );
|
||||||
}
|
}
|
||||||
|
|
||||||
DSN_T GetUnits()
|
DSN_T GetUnits() const
|
||||||
{
|
{
|
||||||
if( unit )
|
if( unit )
|
||||||
return unit->GetUnits();
|
return unit->GetUnits();
|
||||||
|
@ -1693,7 +1821,7 @@ public:
|
||||||
i->Format( out, nestLevel );
|
i->Format( out, nestLevel );
|
||||||
}
|
}
|
||||||
|
|
||||||
DSN_T GetUnits()
|
DSN_T GetUnits() const
|
||||||
{
|
{
|
||||||
if( unit )
|
if( unit )
|
||||||
return unit->GetUnits();
|
return unit->GetUnits();
|
||||||
|
@ -1710,7 +1838,7 @@ public:
|
||||||
* elements contains, i.e. in its "shape" field. This class also implements
|
* elements contains, i.e. in its "shape" field. This class also implements
|
||||||
* the "(outline ...)" element as a dual personality.
|
* the "(outline ...)" element as a dual personality.
|
||||||
*/
|
*/
|
||||||
class SHAPE : public ELEM
|
class SHAPE : public WINDOW
|
||||||
{
|
{
|
||||||
friend class SPECCTRA_DB;
|
friend class SPECCTRA_DB;
|
||||||
|
|
||||||
|
@ -1722,38 +1850,18 @@ class SHAPE : public ELEM
|
||||||
<polygon_descriptor> |
|
<polygon_descriptor> |
|
||||||
<path_descriptor> |
|
<path_descriptor> |
|
||||||
<qarc_descriptor> ]
|
<qarc_descriptor> ]
|
||||||
|
ELEM* shape; // inherited from WINDOW
|
||||||
*/
|
*/
|
||||||
ELEM* shape;
|
|
||||||
|
|
||||||
WINDOWS windows;
|
WINDOWS windows;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SHAPE( ELEM* aParent, DSN_T aType = T_shape ) :
|
SHAPE( ELEM* aParent, DSN_T aType = T_shape ) :
|
||||||
ELEM( aType, aParent )
|
WINDOW( aParent, aType )
|
||||||
{
|
{
|
||||||
connect = T_on;
|
connect = T_on;
|
||||||
shape = 0;
|
|
||||||
}
|
|
||||||
~SHAPE()
|
|
||||||
{
|
|
||||||
delete shape;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetShape( ELEM* aShape )
|
|
||||||
{
|
|
||||||
delete shape;
|
|
||||||
shape = aShape;
|
|
||||||
|
|
||||||
if( aShape )
|
|
||||||
{
|
|
||||||
wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle
|
|
||||||
|| aShape->Type()==T_qarc || aShape->Type()==T_path
|
|
||||||
|| aShape->Type()==T_polygon);
|
|
||||||
|
|
||||||
aShape->SetParent( this );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetConnect( DSN_T aConnect )
|
void SetConnect( DSN_T aConnect )
|
||||||
{
|
{
|
||||||
connect = aConnect;
|
connect = aConnect;
|
||||||
|
@ -1808,6 +1916,12 @@ public:
|
||||||
isRotated = (aRotation != 0.0);
|
isRotated = (aRotation != 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetVertex( const POINT& aPoint )
|
||||||
|
{
|
||||||
|
vertex = aPoint;
|
||||||
|
vertex.FixNegativeZero();
|
||||||
|
}
|
||||||
|
|
||||||
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
{
|
{
|
||||||
const char* quote = out->GetQuoteChar( padstack_id.c_str() );
|
const char* quote = out->GetQuoteChar( padstack_id.c_str() );
|
||||||
|
@ -1830,6 +1944,8 @@ class IMAGE : public ELEM_HOLDER
|
||||||
{
|
{
|
||||||
friend class SPECCTRA_DB;
|
friend class SPECCTRA_DB;
|
||||||
|
|
||||||
|
std::string hash; ///< a hash string used by Compare(), not Format()ed/exported.
|
||||||
|
|
||||||
std::string image_id;
|
std::string image_id;
|
||||||
DSN_T side;
|
DSN_T side;
|
||||||
UNIT_RES* unit;
|
UNIT_RES* unit;
|
||||||
|
@ -1864,42 +1980,53 @@ public:
|
||||||
delete place_rules;
|
delete place_rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Compare
|
||||||
|
* compares two objects of this type and returns <0, 0, or >0.
|
||||||
|
*/
|
||||||
|
static int Compare( IMAGE* lhs, IMAGE* rhs );
|
||||||
|
|
||||||
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
{
|
{
|
||||||
const char* quote = out->GetQuoteChar( image_id.c_str() );
|
const char* quote = out->GetQuoteChar( image_id.c_str() );
|
||||||
|
|
||||||
out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ),
|
out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ),
|
||||||
quote, image_id.c_str(), quote );
|
quote, image_id.c_str(), quote );
|
||||||
|
|
||||||
|
FormatContents( out, nestLevel+1 );
|
||||||
|
|
||||||
|
out->Print( nestLevel, ")\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is here for makeHash()
|
||||||
|
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
|
{
|
||||||
if( side != T_both )
|
if( side != T_both )
|
||||||
out->Print( 0, " (side %s)", LEXER::GetTokenText( side ) );
|
out->Print( 0, " (side %s)", LEXER::GetTokenText( side ) );
|
||||||
|
|
||||||
out->Print( 0, "\n");
|
out->Print( 0, "\n");
|
||||||
|
|
||||||
if( unit )
|
if( unit )
|
||||||
unit->Format( out, nestLevel+1 );
|
unit->Format( out, nestLevel );
|
||||||
|
|
||||||
// format the kids, which in this class are the shapes
|
// format the kids, which in this class are the shapes
|
||||||
ELEM_HOLDER::FormatContents( out, nestLevel+1 );
|
ELEM_HOLDER::FormatContents( out, nestLevel );
|
||||||
|
|
||||||
for( PINS::iterator i=pins.begin(); i!=pins.end(); ++i )
|
for( PINS::iterator i=pins.begin(); i!=pins.end(); ++i )
|
||||||
i->Format( out, nestLevel+1 );
|
i->Format( out, nestLevel );
|
||||||
|
|
||||||
if( rules )
|
if( rules )
|
||||||
rules->Format( out, nestLevel+1 );
|
rules->Format( out, nestLevel );
|
||||||
|
|
||||||
if( place_rules )
|
if( place_rules )
|
||||||
place_rules->Format( out, nestLevel+1 );
|
place_rules->Format( out, nestLevel );
|
||||||
|
|
||||||
for( KEEPOUTS::iterator i=keepouts.begin(); i!=keepouts.end(); ++i )
|
for( KEEPOUTS::iterator i=keepouts.begin(); i!=keepouts.end(); ++i )
|
||||||
i->Format( out, nestLevel+1 );
|
i->Format( out, nestLevel );
|
||||||
|
|
||||||
out->Print( nestLevel, ")\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DSN_T GetUnits()
|
DSN_T GetUnits() const
|
||||||
{
|
{
|
||||||
if( unit )
|
if( unit )
|
||||||
return unit->GetUnits();
|
return unit->GetUnits();
|
||||||
|
@ -1907,12 +2034,20 @@ public:
|
||||||
return ELEM::GetUnits();
|
return ELEM::GetUnits();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
typedef boost::ptr_vector<IMAGE> IMAGES;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class PADSTACK
|
||||||
|
* holds either a via or a pad definition.
|
||||||
|
*/
|
||||||
class PADSTACK : public ELEM_HOLDER
|
class PADSTACK : public ELEM_HOLDER
|
||||||
{
|
{
|
||||||
friend class SPECCTRA_DB;
|
friend class SPECCTRA_DB;
|
||||||
|
|
||||||
|
std::string hash; ///< a hash string used by Compare(), not Format()ed/exported.
|
||||||
|
|
||||||
|
|
||||||
std::string padstack_id;
|
std::string padstack_id;
|
||||||
UNIT_RES* unit;
|
UNIT_RES* unit;
|
||||||
|
|
||||||
|
@ -1942,6 +2077,13 @@ public:
|
||||||
delete rules;
|
delete rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Compare
|
||||||
|
* compares two objects of this type and returns <0, 0, or >0.
|
||||||
|
*/
|
||||||
|
static int Compare( PADSTACK* lhs, PADSTACK* rhs );
|
||||||
|
|
||||||
void SetPadstackId( const char* aPadstackId )
|
void SetPadstackId( const char* aPadstackId )
|
||||||
{
|
{
|
||||||
padstack_id = aPadstackId;
|
padstack_id = aPadstackId;
|
||||||
|
@ -1954,11 +2096,20 @@ public:
|
||||||
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ),
|
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ),
|
||||||
quote, padstack_id.c_str(), quote );
|
quote, padstack_id.c_str(), quote );
|
||||||
|
|
||||||
|
FormatContents( out, nestLevel+1 );
|
||||||
|
|
||||||
|
out->Print( nestLevel, ")\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// this factored out for use by Compare()
|
||||||
|
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
|
{
|
||||||
if( unit )
|
if( unit )
|
||||||
unit->Format( out, nestLevel+1 );
|
unit->Format( out, nestLevel );
|
||||||
|
|
||||||
// format the kids, which in this class are the shapes
|
// format the kids, which in this class are the shapes
|
||||||
ELEM_HOLDER::FormatContents( out, nestLevel+1 );
|
ELEM_HOLDER::FormatContents( out, nestLevel );
|
||||||
|
|
||||||
out->Print( nestLevel+1, "%s", "" );
|
out->Print( nestLevel+1, "%s", "" );
|
||||||
|
|
||||||
|
@ -1982,12 +2133,11 @@ public:
|
||||||
out->Print( 0, "\n" );
|
out->Print( 0, "\n" );
|
||||||
|
|
||||||
if( rules )
|
if( rules )
|
||||||
rules->Format( out, nestLevel+1 );
|
rules->Format( out, nestLevel );
|
||||||
|
|
||||||
out->Print( nestLevel, ")\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DSN_T GetUnits()
|
DSN_T GetUnits() const
|
||||||
{
|
{
|
||||||
if( unit )
|
if( unit )
|
||||||
return unit->GetUnits();
|
return unit->GetUnits();
|
||||||
|
@ -2007,25 +2157,68 @@ typedef boost::ptr_vector<PADSTACK> PADSTACKS;
|
||||||
class LIBRARY : public ELEM
|
class LIBRARY : public ELEM
|
||||||
{
|
{
|
||||||
friend class SPECCTRA_DB;
|
friend class SPECCTRA_DB;
|
||||||
|
|
||||||
UNIT_RES* unit;
|
|
||||||
|
|
||||||
typedef boost::ptr_vector<IMAGE> IMAGES;
|
UNIT_RES* unit;
|
||||||
IMAGES images;
|
IMAGES images;
|
||||||
|
|
||||||
PADSTACKS padstacks;
|
PADSTACKS padstacks;
|
||||||
|
|
||||||
|
/// The start of the vias within the padstacks, which trail the pads.
|
||||||
|
/// This field is not Format()ed.
|
||||||
|
int via_start_index;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LIBRARY( ELEM* aParent, DSN_T aType = T_library ) :
|
LIBRARY( ELEM* aParent, DSN_T aType = T_library ) :
|
||||||
ELEM( aType, aParent )
|
ELEM( aType, aParent )
|
||||||
{
|
{
|
||||||
unit = 0;
|
unit = 0;
|
||||||
|
via_start_index = -1; // 0 or greater means there is at least one via
|
||||||
}
|
}
|
||||||
~LIBRARY()
|
~LIBRARY()
|
||||||
{
|
{
|
||||||
delete unit;
|
delete unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddPadstack( PADSTACK* aPadstack )
|
||||||
|
{
|
||||||
|
padstacks.push_back( aPadstack );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetViaStartIndex( int aIndex )
|
||||||
|
{
|
||||||
|
via_start_index = aIndex;
|
||||||
|
}
|
||||||
|
int GetViaStartIndex()
|
||||||
|
{
|
||||||
|
return via_start_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FindIMAGE( IMAGE* aImage )
|
||||||
|
{
|
||||||
|
for( unsigned i=0; i<images.size(); ++i )
|
||||||
|
{
|
||||||
|
if( 0 == IMAGE::Compare( aImage, &images[i] ) )
|
||||||
|
return (int) i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppendIMAGE( IMAGE* aImage )
|
||||||
|
{
|
||||||
|
aImage->SetParent( this );
|
||||||
|
images.push_back( aImage );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LookupIMAGE( IMAGE* aImage )
|
||||||
|
{
|
||||||
|
int ndx = FindIMAGE( aImage );
|
||||||
|
if( ndx == -1 )
|
||||||
|
{
|
||||||
|
AppendIMAGE( aImage );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
|
||||||
{
|
{
|
||||||
|
@ -2039,18 +2232,13 @@ public:
|
||||||
i->Format( out, nestLevel );
|
i->Format( out, nestLevel );
|
||||||
}
|
}
|
||||||
|
|
||||||
DSN_T GetUnits()
|
DSN_T GetUnits() const
|
||||||
{
|
{
|
||||||
if( unit )
|
if( unit )
|
||||||
return unit->GetUnits();
|
return unit->GetUnits();
|
||||||
|
|
||||||
return ELEM::GetUnits();
|
return ELEM::GetUnits();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPadstack( PADSTACK* aPadstack )
|
|
||||||
{
|
|
||||||
padstacks.push_back( aPadstack );
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2422,6 +2610,8 @@ public:
|
||||||
|
|
||||||
class CONNECT : public ELEM
|
class CONNECT : public ELEM
|
||||||
{
|
{
|
||||||
|
// @todo not completed.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CONNECT( ELEM* parent ) :
|
CONNECT( ELEM* parent ) :
|
||||||
ELEM( T_connect, parent ) {}
|
ELEM( T_connect, parent ) {}
|
||||||
|
@ -2695,7 +2885,7 @@ public:
|
||||||
i->Format( out, nestLevel );
|
i->Format( out, nestLevel );
|
||||||
}
|
}
|
||||||
|
|
||||||
DSN_T GetUnits()
|
DSN_T GetUnits() const
|
||||||
{
|
{
|
||||||
if( unit )
|
if( unit )
|
||||||
return unit->GetUnits();
|
return unit->GetUnits();
|
||||||
|
@ -2780,7 +2970,7 @@ public:
|
||||||
out->Print( nestLevel, ")\n" );
|
out->Print( nestLevel, ")\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
DSN_T GetUnits()
|
DSN_T GetUnits() const
|
||||||
{
|
{
|
||||||
if( unit )
|
if( unit )
|
||||||
return unit->GetUnits();
|
return unit->GetUnits();
|
||||||
|
@ -3179,6 +3369,8 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
|
||||||
wxString filename;
|
wxString filename;
|
||||||
|
|
||||||
std::string quote_char;
|
std::string quote_char;
|
||||||
|
|
||||||
|
STRINGFORMATTER sf;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3321,6 +3513,22 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
|
||||||
void doSUPPLY_PIN( SUPPLY_PIN* growth ) throw( IOError );
|
void doSUPPLY_PIN( SUPPLY_PIN* growth ) throw( IOError );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function makeIMAGE
|
||||||
|
* allocates an IMAGE on the heap and creates all the PINs according
|
||||||
|
* to the PADs in the MODULE.
|
||||||
|
*/
|
||||||
|
IMAGE* makeIMAGE( MODULE* aModule );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function makePADSTACKs
|
||||||
|
* makes all the PADSTACKs, and marks each D_PAD with the index into the
|
||||||
|
* LIBRARY::padstacks list that it matches.
|
||||||
|
*/
|
||||||
|
void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads );
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SPECCTRA_DB()
|
SPECCTRA_DB()
|
||||||
|
@ -3332,7 +3540,7 @@ public:
|
||||||
quote_char += '"';
|
quote_char += '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
~SPECCTRA_DB()
|
virtual ~SPECCTRA_DB()
|
||||||
{
|
{
|
||||||
delete lexer;
|
delete lexer;
|
||||||
delete pcb;
|
delete pcb;
|
||||||
|
|
|
@ -234,14 +234,43 @@ static QARC* makeArc( const POINT& aStart, const POINT& aEnd,
|
||||||
qarc->SetLayerId( aLayerName.c_str() );
|
qarc->SetLayerId( aLayerName.c_str() );
|
||||||
return qarc;
|
return qarc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function makePADSTACKs
|
IMAGE* SPECCTRA_DB::makeIMAGE( MODULE* aModule )
|
||||||
* makes all the PADSTACKs, and marks each D_PAD with the index into the
|
{
|
||||||
* LIBRARY::padstacks list that it matches.
|
TYPE_COLLECTOR items;
|
||||||
*/
|
|
||||||
static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibrary )
|
static const KICAD_T scanPADs[] = { TYPEPAD, EOT };
|
||||||
|
|
||||||
|
PADSTACKS& padstacks = pcb->library->padstacks;
|
||||||
|
|
||||||
|
// get all the MODULE's pads.
|
||||||
|
items.Collect( aModule, scanPADs );
|
||||||
|
|
||||||
|
IMAGE* image = new IMAGE( 0 );
|
||||||
|
|
||||||
|
image->image_id = CONV_TO_UTF8( aModule->m_LibRef );
|
||||||
|
|
||||||
|
// collate all the pads, and make a component.
|
||||||
|
for( int p=0; p<items.GetCount(); ++p )
|
||||||
|
{
|
||||||
|
D_PAD* pad = (D_PAD*) items[p];
|
||||||
|
|
||||||
|
PADSTACK* padstack = &padstacks[pad->m_logical_connexion];
|
||||||
|
|
||||||
|
PIN* pin = new PIN(image);
|
||||||
|
image->pins.push_back( pin );
|
||||||
|
|
||||||
|
pin->padstack_id = padstack->padstack_id;
|
||||||
|
pin->pin_id = CONV_TO_UTF8( pad->ReturnStringPadName() );
|
||||||
|
pin->SetVertex( mapPt( pad->m_Pos0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
|
||||||
{
|
{
|
||||||
char name[80]; // padstack name builder
|
char name[80]; // padstack name builder
|
||||||
|
|
||||||
|
@ -251,7 +280,6 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
|
||||||
}
|
}
|
||||||
|
|
||||||
D_PAD* old_pad = NULL;
|
D_PAD* old_pad = NULL;
|
||||||
int padstackNdx = 0;
|
|
||||||
|
|
||||||
#define COPPER_LAYERS 2 // top and bottom
|
#define COPPER_LAYERS 2 // top and bottom
|
||||||
|
|
||||||
|
@ -262,7 +290,7 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
|
||||||
// within a pad's padstack. this is usually correct, but not rigorous. We could do
|
// within a pad's padstack. this is usually correct, but not rigorous. We could do
|
||||||
// better if there was actually a "layer type" field within Kicad which would
|
// better if there was actually a "layer type" field within Kicad which would
|
||||||
// hold one of: T_signal, T_power, T_mixed, T_jumper
|
// hold one of: T_signal, T_power, T_mixed, T_jumper
|
||||||
// See page bottom of page 74 of the SECCTRA Design Language Reference, May 2000.
|
// See bottom of page 74 of the SECCTRA Design Language Reference, May 2000.
|
||||||
|
|
||||||
std::string layerId[COPPER_LAYERS] = {
|
std::string layerId[COPPER_LAYERS] = {
|
||||||
CONV_TO_UTF8(aBoard->GetLayerName( LAYER_CMP_N )),
|
CONV_TO_UTF8(aBoard->GetLayerName( LAYER_CMP_N )),
|
||||||
|
@ -270,8 +298,9 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// late breaking news, we can use "signal" as the layer name and report the
|
// Late breaking news: we can use the reserved layer name "signal" and report the
|
||||||
// padstack as a single layer.
|
// padstack as a single layer. See <reserved_layer_name> in the spec.
|
||||||
|
// But this probably gives problems for a "power" layer or power pin, we'll see.
|
||||||
reportedLayers = 1;
|
reportedLayers = 1;
|
||||||
layerId[0] = "signal";
|
layerId[0] = "signal";
|
||||||
#endif
|
#endif
|
||||||
|
@ -280,8 +309,6 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
|
||||||
{
|
{
|
||||||
D_PAD* pad = (D_PAD*) aPads[i];
|
D_PAD* pad = (D_PAD*) aPads[i];
|
||||||
|
|
||||||
pad->m_logical_connexion = padstackNdx;
|
|
||||||
|
|
||||||
bool doLayer[COPPER_LAYERS] = {
|
bool doLayer[COPPER_LAYERS] = {
|
||||||
pad->IsOnLayer( LAYER_CMP_N ),
|
pad->IsOnLayer( LAYER_CMP_N ),
|
||||||
pad->IsOnLayer( COPPER_LAYER_N )
|
pad->IsOnLayer( COPPER_LAYER_N )
|
||||||
|
@ -289,6 +316,10 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
|
||||||
|
|
||||||
if( old_pad && 0==D_PAD::Compare( old_pad, pad ) )
|
if( old_pad && 0==D_PAD::Compare( old_pad, pad ) )
|
||||||
{
|
{
|
||||||
|
// padstacks.size()-1 is the index of the matching padstack in LIBRARY::padstacks
|
||||||
|
pad->m_logical_connexion = pcb->library->padstacks.size()-1;
|
||||||
|
|
||||||
|
// this is the same as the last pad, so do not add it to the padstack list.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,6 +327,9 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
|
||||||
// an "image->keepout" later. No copper pad here, it is probably a hole.
|
// an "image->keepout" later. No copper pad here, it is probably a hole.
|
||||||
if( !doLayer[0] && !doLayer[1] )
|
if( !doLayer[0] && !doLayer[1] )
|
||||||
{
|
{
|
||||||
|
// padstacks.size()-1 is the index of the matching padstack in LIBRARY::padstacks
|
||||||
|
pad->m_logical_connexion = pcb->library->padstacks.size()-1;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,11 +339,11 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
|
||||||
|
|
||||||
old_pad = pad;
|
old_pad = pad;
|
||||||
|
|
||||||
// this is the index into the library->padstacks, be careful.
|
PADSTACK* padstack = new PADSTACK( pcb->library );
|
||||||
pad->m_logical_connexion = padstackNdx++;
|
pcb->library->AddPadstack( padstack );
|
||||||
|
|
||||||
PADSTACK* padstack = new PADSTACK( aLibrary );
|
// padstacks.size()-1 is the index of the matching padstack in LIBRARY::padstacks
|
||||||
aLibrary->AddPadstack( padstack );
|
pad->m_logical_connexion = pcb->library->padstacks.size()-1;
|
||||||
|
|
||||||
// paddOfset is the offset of copper shape relative to hole position,
|
// paddOfset is the offset of copper shape relative to hole position,
|
||||||
// and pad->m_Pos is hole position. All shapes must be shifted by
|
// and pad->m_Pos is hole position. All shapes must be shifted by
|
||||||
|
@ -331,12 +365,10 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
|
||||||
{
|
{
|
||||||
if( doLayer[layer] )
|
if( doLayer[layer] )
|
||||||
{
|
{
|
||||||
CIRCLE* circle;
|
|
||||||
SHAPE* shape = new SHAPE( padstack );
|
SHAPE* shape = new SHAPE( padstack );
|
||||||
|
|
||||||
padstack->Append( shape );
|
padstack->Append( shape );
|
||||||
|
|
||||||
circle = new CIRCLE( shape );
|
CIRCLE* circle = new CIRCLE( shape );
|
||||||
shape->SetShape( circle );
|
shape->SetShape( circle );
|
||||||
|
|
||||||
circle->SetLayerId( layerId[layer].c_str() );
|
circle->SetLayerId( layerId[layer].c_str() );
|
||||||
|
@ -347,7 +379,6 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf( name, sizeof(name), "Round%dPad_%.6g_mil", coppers, scale(pad->m_Size.x) );
|
snprintf( name, sizeof(name), "Round%dPad_%.6g_mil", coppers, scale(pad->m_Size.x) );
|
||||||
|
|
||||||
name[ sizeof(name)-1 ] = 0;
|
name[ sizeof(name)-1 ] = 0;
|
||||||
|
|
||||||
// @todo verify that all pad names are unique, there is a chance that
|
// @todo verify that all pad names are unique, there is a chance that
|
||||||
|
@ -536,9 +567,13 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
|
||||||
int defaultViaSize = aBoard->m_BoardSettings->m_CurrentViaSize;
|
int defaultViaSize = aBoard->m_BoardSettings->m_CurrentViaSize;
|
||||||
if( defaultViaSize )
|
if( defaultViaSize )
|
||||||
{
|
{
|
||||||
PADSTACK* padstack = new PADSTACK( aLibrary );
|
PADSTACK* padstack = new PADSTACK( pcb->library );
|
||||||
aLibrary->AddPadstack( padstack );
|
pcb->library->AddPadstack( padstack );
|
||||||
padstackNdx++; // remember this index, it is the default via
|
|
||||||
|
// remember this index, it is the default via and also the start of the
|
||||||
|
// vias within the padstack list. Before this index are the pads.
|
||||||
|
// At this index and later are the vias.
|
||||||
|
pcb->library->SetViaStartIndex( pcb->library->padstacks.size()-1 );
|
||||||
|
|
||||||
SHAPE* shape = new SHAPE( padstack );
|
SHAPE* shape = new SHAPE( padstack );
|
||||||
padstack->Append( shape );
|
padstack->Append( shape );
|
||||||
|
@ -560,9 +595,8 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
|
||||||
if( viaSize == defaultViaSize )
|
if( viaSize == defaultViaSize )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
PADSTACK* padstack = new PADSTACK( aLibrary );
|
PADSTACK* padstack = new PADSTACK( pcb->library );
|
||||||
aLibrary->AddPadstack( padstack );
|
pcb->library->AddPadstack( padstack );
|
||||||
padstackNdx++; // remember this index, it is the default via
|
|
||||||
|
|
||||||
SHAPE* shape = new SHAPE( padstack );
|
SHAPE* shape = new SHAPE( padstack );
|
||||||
padstack->Append( shape );
|
padstack->Append( shape );
|
||||||
|
@ -575,10 +609,6 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
|
||||||
snprintf( name, sizeof(name), "Via_%.6g_mil", scale(viaSize) );
|
snprintf( name, sizeof(name), "Via_%.6g_mil", scale(viaSize) );
|
||||||
name[ sizeof(name)-1 ] = 0;
|
name[ sizeof(name)-1 ] = 0;
|
||||||
|
|
||||||
// @todo verify that all pad names are unique, there is a chance that
|
|
||||||
// D_PAD::Compare() could say two pads are different, yet they get the same
|
|
||||||
// name here. If so, blend in the padNdx into the name.
|
|
||||||
|
|
||||||
padstack->SetPadstackId( name );
|
padstack->SetPadstackId( name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -593,7 +623,6 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
|
||||||
if( !pcb )
|
if( !pcb )
|
||||||
pcb = SPECCTRA_DB::MakePCB();
|
pcb = SPECCTRA_DB::MakePCB();
|
||||||
|
|
||||||
|
|
||||||
// DSN Images (=Kicad MODULES and pads) must be presented from the
|
// DSN Images (=Kicad MODULES and pads) must be presented from the
|
||||||
// top view. So we temporarily flip any modules which are on the back
|
// top view. So we temporarily flip any modules which are on the back
|
||||||
// side of the board to the front, and record this in the MODULE's flag field.
|
// side of the board to the front, and record this in the MODULE's flag field.
|
||||||
|
@ -661,8 +690,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
|
||||||
rect->layer_id = "pcb";
|
rect->layer_id = "pcb";
|
||||||
|
|
||||||
// opposite corners
|
// opposite corners
|
||||||
rect->point0 = ppairs[0].p1;
|
rect->SetCorners( ppairs[0].p1, ppairs[2].p1 );
|
||||||
rect->point1 = ppairs[2].p1;
|
|
||||||
|
|
||||||
boundary->rectangle = rect;
|
boundary->rectangle = rect;
|
||||||
}
|
}
|
||||||
|
@ -763,55 +791,61 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
|
||||||
// but in that case they are WINDOWs within the COPPER_PLANEs.
|
// but in that case they are WINDOWs within the COPPER_PLANEs.
|
||||||
|
|
||||||
|
|
||||||
//-----<build the padstack list here, no output>------------------------
|
//-----<build the initial padstack list>--------------------------------
|
||||||
{
|
{
|
||||||
static const KICAD_T scanPADs[] = { TYPEPAD, EOT };
|
|
||||||
|
|
||||||
TYPE_COLLECTOR pads;
|
TYPE_COLLECTOR pads;
|
||||||
|
static const KICAD_T scanPADs[] = { TYPEPAD, EOT };
|
||||||
// get all the D_PADs into pads.
|
|
||||||
|
// get all the D_PADs into 'pads'.
|
||||||
pads.Collect( aBoard, scanPADs );
|
pads.Collect( aBoard, scanPADs );
|
||||||
|
|
||||||
makePADSTACKs( aBoard, pads, pcb->library );
|
makePADSTACKs( aBoard, pads );
|
||||||
|
|
||||||
|
|
||||||
#if 0 && defined(DEBUG)
|
#if 0 && defined(DEBUG)
|
||||||
for( int p=0; p<pads.GetCount(); ++p )
|
for( int p=0; p<pads.GetCount(); ++p )
|
||||||
pads[p]->Show( 0, std::cout );
|
pads[p]->Show( 0, std::cout );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----<via_descriptor>-------------------------------------------------
|
|
||||||
{
|
|
||||||
// Output the vias in the padstack list here, by name
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----<build the images>----------------------------------------------
|
//-----<build the images>----------------------------------------------
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
static const KICAD_T scanMODULEs[] = { TYPEMODULE, EOT };
|
static const KICAD_T scanMODULEs[] = { TYPEMODULE, EOT };
|
||||||
|
|
||||||
items.Collect( aBoard, scanMODULEs );
|
items.Collect( aBoard, scanMODULEs );
|
||||||
|
|
||||||
for( int m=0; m<items.GetCount(); ++m )
|
for( int m=0; m<items.GetCount(); ++m )
|
||||||
{
|
{
|
||||||
MODULE* module = (MODULE*) items[m];
|
MODULE* module = (MODULE*) items[m];
|
||||||
|
|
||||||
// collate all the pads, and make a component.
|
IMAGE* image = makeIMAGE( module );
|
||||||
for( int p=0; p<pads.GetCount(); ++p )
|
|
||||||
|
if( pcb->library->LookupIMAGE( image ) )
|
||||||
{
|
{
|
||||||
D_PAD* pad = (D_PAD*) pads[p];
|
delete image;
|
||||||
|
|
||||||
D(pad->Show( 0, std::cout );)
|
|
||||||
|
|
||||||
// lookup and maybe add this pad to the padstack.
|
|
||||||
wxString padName = lookupPad( pcb->library->padstacks, pad );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----<via_descriptor>-------------------------------------------------
|
||||||
|
{
|
||||||
|
// Output the vias in the padstack list here, by name
|
||||||
|
VIA* vias = pcb->structure->via;
|
||||||
|
PADSTACKS& padstacks = pcb->library->padstacks;
|
||||||
|
int viaNdx = pcb->library->via_start_index;
|
||||||
|
|
||||||
|
if( viaNdx != -1 )
|
||||||
|
{
|
||||||
|
for( ; viaNdx < (int)padstacks.size(); ++viaNdx )
|
||||||
|
{
|
||||||
|
vias->AppendVia( padstacks[viaNdx].padstack_id.c_str() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----<restore MODULEs>------------------------------------------------
|
||||||
|
|
||||||
// DSN Images (=Kicad MODULES and pads) must be presented from the
|
// DSN Images (=Kicad MODULES and pads) must be presented from the
|
||||||
// top view. Restore those that were flipped.
|
// top view. Restore those that were flipped.
|
||||||
for( MODULE* module = aBoard->m_Modules; module; module = module->Next() )
|
for( MODULE* module = aBoard->m_Modules; module; module = module->Next() )
|
||||||
|
@ -822,6 +856,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
|
||||||
module->flag = 0;
|
module->flag = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue