Gerbview: fixed an issue with some gerber files. Added Image Justify support (partial support).
This commit is contained in:
parent
a911720adf
commit
de37bbad17
|
@ -151,6 +151,9 @@ void GERBER_IMAGE::ResetDefaultValues()
|
|||
m_FileName.Empty();
|
||||
m_ImageName = wxT( "no name" ); // Image name from the IN command
|
||||
m_ImageNegative = false; // true = Negative image
|
||||
m_ImageJustifyOffset = wxPoint(0,0); // Image justify Offset
|
||||
m_ImageJustifyXCenter = false; // Image Justify Center on X axis (default = false)
|
||||
m_ImageJustifyYCenter = false; // Image Justify Center on Y axis (default = false)
|
||||
m_GerbMetric = false; // false = Inches (default), true = metric
|
||||
m_Relative = false; // false = absolute Coord,
|
||||
// true = relative Coord
|
||||
|
@ -271,3 +274,45 @@ void GERBER_IMAGE::StepAndRepeatItem( const GERBER_DRAW_ITEM& aItem )
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Function DisplayInfo
|
||||
* has knowledge about the frame and how and where to put status information
|
||||
* about this object into the frame's message panel.
|
||||
* Display info about Image Parameters.
|
||||
*/
|
||||
void GERBER_IMAGE::DisplayImageInfo( void )
|
||||
{
|
||||
wxString msg;
|
||||
|
||||
m_Parent->ClearMsgPanel();
|
||||
|
||||
// Display Image name
|
||||
m_Parent->AppendMsgPanel( _( "Image name" ), m_ImageName, BROWN );
|
||||
|
||||
// Display graphic layer number
|
||||
msg.Printf( wxT( "%d" ), m_GraphicLayer + 1 );
|
||||
m_Parent->AppendMsgPanel( _( "Graphic layer" ), msg, BROWN );
|
||||
|
||||
// This next info can be see as debug info, so it can be disabled
|
||||
|
||||
// Display rotation
|
||||
msg.Printf( wxT( "%d" ), m_ImageRotation / 10 );
|
||||
m_Parent->AppendMsgPanel( _( "Rotation" ), msg, CYAN );
|
||||
|
||||
// Display Image justification;
|
||||
msg = m_ImageJustifyXCenter ? _("Center") : _("Normal");
|
||||
m_Parent->AppendMsgPanel( _( "X Justify" ), msg, DARKRED );
|
||||
|
||||
msg = m_ImageJustifyYCenter ? _("Center") : _("Normal");
|
||||
m_Parent->AppendMsgPanel( _( "Y Justify" ), msg, DARKRED );
|
||||
|
||||
if( g_UserUnit == INCHES )
|
||||
msg.Printf( wxT( "X=%f Y=%f" ), (double) m_ImageJustifyOffset.x/10000,
|
||||
(double) m_ImageJustifyOffset.y/10000 );
|
||||
else
|
||||
msg.Printf( wxT( "X=%f Y=%f" ), (double) m_ImageJustifyOffset.x*2.54/1000,
|
||||
(double) m_ImageJustifyOffset.y*2.54/1000 );
|
||||
m_Parent->AppendMsgPanel( _( "Image Justify Offset" ), msg, CYAN );
|
||||
}
|
||||
|
||||
|
|
|
@ -86,6 +86,9 @@ public:
|
|||
wxString m_ImageName; // Image name, from IN <name>* command
|
||||
int m_GraphicLayer; // Graphic layer Number
|
||||
bool m_ImageNegative; // true = Negative image
|
||||
bool m_ImageJustifyXCenter; // Image Justify Center on X axis (default = false)
|
||||
bool m_ImageJustifyYCenter; // Image Justify Center on Y axis (default = false)
|
||||
wxPoint m_ImageJustifyOffset; // Image Justify Offset on XY axis (default = 0,0)
|
||||
bool m_GerbMetric; // false = Inches, true = metric
|
||||
bool m_Relative; // false = absolute Coord, true = relative Coord
|
||||
bool m_NoTrailingZeros; // true: remove tailing zeros.
|
||||
|
@ -236,6 +239,13 @@ public:
|
|||
* @param aItem = the item to repeat
|
||||
*/
|
||||
void StepAndRepeatItem( const GERBER_DRAW_ITEM& aItem );
|
||||
|
||||
/** Function DisplayImageInfo
|
||||
* has knowledge about the frame and how and where to put status information
|
||||
* about this object into the frame's message panel.
|
||||
* Display info about Image Parameters.
|
||||
*/
|
||||
void DisplayImageInfo( void );
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ wxPoint GERBER_DRAW_ITEM::GetABPosition( const wxPoint& aXYPosition )
|
|||
* For instance: Rotation must be made after or before mirroring ?
|
||||
* Note: if something is changed here, GetYXPosition must reflect changes
|
||||
*/
|
||||
wxPoint abPos = aXYPosition;
|
||||
wxPoint abPos = aXYPosition + m_imageParams->m_ImageJustifyOffset;
|
||||
|
||||
if( m_swapAxis )
|
||||
EXCHG( abPos.x, abPos.y );
|
||||
|
@ -165,7 +165,7 @@ wxPoint GERBER_DRAW_ITEM::GetXYPosition( const wxPoint& aABPosition )
|
|||
xyPos -= m_layerOffset + m_imageParams->m_ImageOffset;
|
||||
if( m_swapAxis )
|
||||
EXCHG( xyPos.x, xyPos.y );
|
||||
return xyPos;
|
||||
return xyPos - m_imageParams->m_ImageJustifyOffset;
|
||||
}
|
||||
|
||||
|
||||
|
@ -458,7 +458,7 @@ void GERBER_DRAW_ITEM::DrawGbrPoly( EDA_Rect* aClipBox,
|
|||
/** Function DisplayInfo
|
||||
* has knowledge about the frame and how and where to put status information
|
||||
* about this object into the frame's message panel.
|
||||
* Display info about the track segment only, and does not calculate the full track length
|
||||
* Display info about this GERBER item
|
||||
* @param frame A WinEDA_DrawFrame in which to print status information.
|
||||
*/
|
||||
void GERBER_DRAW_ITEM::DisplayInfo( WinEDA_DrawFrame* frame )
|
||||
|
@ -473,13 +473,6 @@ void GERBER_DRAW_ITEM::DisplayInfo( WinEDA_DrawFrame* frame )
|
|||
msg.Printf( wxT( "%d" ), m_DCode );
|
||||
frame->AppendMsgPanel( _( "D Code" ), msg, RED );
|
||||
|
||||
// Display Image name
|
||||
if( m_imageParams )
|
||||
{
|
||||
msg = m_imageParams->m_ImageName;
|
||||
frame->AppendMsgPanel( _( "Image name" ), msg, BROWN );
|
||||
}
|
||||
|
||||
// Display graphic layer number
|
||||
msg.Printf( wxT( "%d" ), GetLayer() + 1 );
|
||||
frame->AppendMsgPanel( _( "Graphic layer" ), msg, BROWN );
|
||||
|
|
|
@ -209,7 +209,7 @@ public:
|
|||
* has knowledge about the frame and how and where to put status information
|
||||
* about this object into the frame's message panel.
|
||||
* Is virtual from EDA_BaseStruct.
|
||||
* Display info about the track segment and the full track length
|
||||
* Display info about this GERBER item
|
||||
* @param frame A WinEDA_DrawFrame in which to print status information.
|
||||
*/
|
||||
void DisplayInfo( WinEDA_DrawFrame* frame );
|
||||
|
|
|
@ -37,6 +37,12 @@ void WinEDA_GerberFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
|
|||
{
|
||||
DrawStruct = GerberGeneralLocateAndDisplay();
|
||||
GetScreen()->SetCurItem( DrawStruct );
|
||||
if( DrawStruct == NULL )
|
||||
{
|
||||
GERBER_IMAGE* gerber = g_GERBER_List[getActiveLayer() ];
|
||||
if( gerber )
|
||||
gerber->DisplayImageInfo( );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
G04 Test image justify 1*
|
||||
G04 Crosshairs should be justified to the X axis *
|
||||
G04 and 0.5 inches offset from Y axis *
|
||||
G04 Handcoded by Julian Lamb *
|
||||
%MOIN*%
|
||||
%FSLAX23Y23*%
|
||||
%IJB.5*%
|
||||
%ADD10C,0.050*%
|
||||
|
||||
G04 Crosshairs *
|
||||
X-1000Y0D02*
|
||||
G54D10*
|
||||
X1000Y0D01*
|
||||
|
||||
X0Y-1000D02*
|
||||
G54D10*
|
||||
X0Y1000D01*
|
||||
|
||||
M02*
|
|
@ -0,0 +1,18 @@
|
|||
G04 Test image offset *
|
||||
G04 Crosshairs should be centered on 0,0 in final rendering*
|
||||
G04 Handcoded by Julian Lamb *
|
||||
%MOIN*%
|
||||
%FSLAX23Y23*%
|
||||
%IOA-2.0B-1.0*%
|
||||
%ADD10C,0.050*%
|
||||
|
||||
G04 Crosshairs to be on 0,0 *
|
||||
X1000Y1000D02*
|
||||
G54D10*
|
||||
X3000Y1000D01*
|
||||
|
||||
X2000Y0D02*
|
||||
G54D10*
|
||||
X2000Y2000D01*
|
||||
|
||||
M02*
|
|
@ -11,6 +11,9 @@
|
|||
|
||||
#define CODE( x, y ) ( ( (x) << 8 ) + (y) )
|
||||
|
||||
// Helper function to read a primitive macro param (TODO: make it DCODE_PARAM function)
|
||||
static bool ReadMacroParam( DCODE_PARAM& aParam, char*& aText );
|
||||
|
||||
// See rs274xrevd_e.pdf, table 1: RS-274X parameters order of entry
|
||||
// in gerber files, when a coordinate is given (like X78Y600 or I0J80):
|
||||
// Y and Y are logical coordinates
|
||||
|
@ -94,14 +97,16 @@ static int ReadXCommand( char*& text )
|
|||
* 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 int - The int read in.
|
||||
* @param aSkipSeparator = true (default) to skip comma
|
||||
* @return int - The int read in.
|
||||
*/
|
||||
static int ReadInt( char*& text )
|
||||
static int ReadInt( char*& text, bool aSkipSeparator = true )
|
||||
{
|
||||
int ret = (int) strtol( text, &text, 10 );
|
||||
|
||||
if( *text == ',' || isspace( *text ) )
|
||||
++text;
|
||||
if( aSkipSeparator )
|
||||
++text;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -113,14 +118,16 @@ static int ReadInt( char*& text )
|
|||
* 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 )
|
||||
static double ReadDouble( char*& text, bool aSkipSeparator = true )
|
||||
{
|
||||
double ret = strtod( text, &text );
|
||||
|
||||
if( *text == ',' || isspace( *text ) )
|
||||
++text;
|
||||
if( aSkipSeparator )
|
||||
++text;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -427,11 +434,68 @@ bool GERBER_IMAGE::ExecuteRS274XCommand( int command,
|
|||
}
|
||||
break;
|
||||
|
||||
case IMAGE_JUSTIFY:
|
||||
case PLOTTER_FILM:
|
||||
case IMAGE_JUSTIFY: // Command IJAnBn*
|
||||
m_ImageJustifyXCenter = false; // Image Justify Center on X axis (default = false)
|
||||
m_ImageJustifyYCenter = false; // Image Justify Center on Y axis (default = false)
|
||||
m_ImageJustifyOffset = wxPoint(0,0); // Image Justify Offset on XY axis (default = 0,0)
|
||||
while( *text && *text != '*' )
|
||||
{
|
||||
// IJ command is (for A or B axis) AC or AL or A<coordinate>
|
||||
switch( *text )
|
||||
{
|
||||
case 'A': // A axis justify
|
||||
text++;
|
||||
if( *text == 'C' )
|
||||
{
|
||||
m_ImageJustifyXCenter = true;
|
||||
text++;
|
||||
}
|
||||
else if( *text == 'L' )
|
||||
{
|
||||
m_ImageJustifyXCenter = true;
|
||||
text++;
|
||||
}
|
||||
else m_ImageJustifyOffset.x = wxRound( ReadDouble( text ) * conv_scale);
|
||||
break;
|
||||
|
||||
case 'B': // B axis justify
|
||||
text++;
|
||||
if( *text == 'C' )
|
||||
{
|
||||
m_ImageJustifyYCenter = true;
|
||||
text++;
|
||||
}
|
||||
else if( *text == 'L' )
|
||||
{
|
||||
m_ImageJustifyYCenter = true;
|
||||
text++;
|
||||
}
|
||||
else m_ImageJustifyOffset.y = wxRound( ReadDouble( text ) * conv_scale);
|
||||
break;
|
||||
default:
|
||||
text++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( m_ImageJustifyXCenter )
|
||||
m_ImageJustifyOffset.x = 0;
|
||||
if( m_ImageJustifyYCenter )
|
||||
m_ImageJustifyOffset.y = 0;
|
||||
break;
|
||||
|
||||
case KNOCKOUT:
|
||||
msg.Printf( _( "RS274X: Command \"%c%c\" ignored by Gerbview" ),
|
||||
(command >> 8) & 0xFF, command & 0xFF );
|
||||
msg = _( "RS274X: Command KNOCKOUT ignored by Gerbview" ) ;
|
||||
ReportMessage( msg );
|
||||
break;
|
||||
|
||||
case PLOTTER_FILM: // Command PF <string>
|
||||
// This is an info about film that must be used to plot this file
|
||||
// Has no meaning here. We just display this string
|
||||
msg = ( "Plotter Film info:<br>" );
|
||||
while( *text != '*' )
|
||||
{
|
||||
msg.Append( *text++ );
|
||||
}
|
||||
ReportMessage( msg );
|
||||
break;
|
||||
|
||||
|
@ -498,10 +562,10 @@ bool GERBER_IMAGE::ExecuteRS274XCommand( int command,
|
|||
m_FilesPtr++;
|
||||
break;
|
||||
|
||||
case AP_MACRO:
|
||||
case AP_MACRO: // lines like %AMMYMACRO*
|
||||
// 5,1,8,0,0,1.08239X$1,22.5*
|
||||
// %
|
||||
ok = ReadApertureMacro( buff, text, m_Current_File );
|
||||
if( !ok )
|
||||
break;
|
||||
break;
|
||||
|
||||
case AP_DEFINITION:
|
||||
|
@ -729,24 +793,39 @@ bool GetEndOfBlock( char buff[GERBER_BUFZ], char*& text, FILE* gerber_file )
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static bool CheckForLineEnd( char buff[GERBER_BUFZ], char*& text, FILE* fp )
|
||||
/** function GetNextLine
|
||||
* test for an end of line
|
||||
* if an end of line is found:
|
||||
* read a new line
|
||||
* @param aBuff[GERBER_BUFZ] = buffer to fill with a new line
|
||||
* @param aText = pointer to the last useful char in aBuff
|
||||
* on return: points the beginning of the next line.
|
||||
* @param aFile = the opened GERBER file to read
|
||||
* @return a pointer to the beginning of the next line or NULL if end of file
|
||||
*/
|
||||
static char* GetNextLine( char aBuff[GERBER_BUFZ], char* aText, FILE* aFile )
|
||||
{
|
||||
while( *text == '\n' || *text == '\r' || !*text )
|
||||
for( ; ; )
|
||||
{
|
||||
if( *text == '\n' || *text == '\r' )
|
||||
++text;
|
||||
|
||||
if( !*text )
|
||||
switch (*aText )
|
||||
{
|
||||
if( fgets( buff, GERBER_BUFZ, fp ) == NULL )
|
||||
return false;
|
||||
case ' ': // skip blanks
|
||||
case '\n':
|
||||
case '\r': // Skip line terminators
|
||||
++aText;
|
||||
break;
|
||||
|
||||
text = buff;
|
||||
case 0: // End of text found in aBuff: Read a new string
|
||||
if( fgets( aBuff, GERBER_BUFZ, aFile ) == NULL )
|
||||
return NULL;
|
||||
aText = aBuff;
|
||||
return aText;
|
||||
|
||||
default:
|
||||
return aText;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return aText;
|
||||
}
|
||||
|
||||
|
||||
|
@ -769,24 +848,28 @@ bool GERBER_IMAGE::ReadApertureMacro( char buff[GERBER_BUFZ],
|
|||
am.name.Append( *text++ );
|
||||
}
|
||||
|
||||
// Read aperture macro parameters
|
||||
for( ; ; )
|
||||
{
|
||||
AM_PRIMITIVE prim( m_GerbMetric );
|
||||
|
||||
if( *text == '*' )
|
||||
++text;
|
||||
|
||||
if( !CheckForLineEnd( buff, text, gerber_file ) )
|
||||
text = GetNextLine( buff, text, gerber_file ); // Get next line
|
||||
if( text == NULL ) // End of File
|
||||
return false;
|
||||
|
||||
// text points the beginning of a new line.
|
||||
|
||||
// Test for the last line in aperture macro lis:
|
||||
// last line is % or *% sometime found.
|
||||
if( *text == '*' )
|
||||
++text;
|
||||
if( *text == '%' )
|
||||
break; // exit with text still pointing at %
|
||||
|
||||
prim.primitive_id = (AM_PRIMITIVE_ID) ReadInt( text );
|
||||
|
||||
int paramCount;
|
||||
|
||||
switch( prim.primitive_id )
|
||||
int paramCount = 0;
|
||||
int primitive_type = ReadInt( text );
|
||||
switch( primitive_type )
|
||||
{
|
||||
case AMP_CIRCLE:
|
||||
paramCount = 4;
|
||||
|
@ -823,30 +906,26 @@ bool GERBER_IMAGE::ReadApertureMacro( char buff[GERBER_BUFZ],
|
|||
break;
|
||||
|
||||
default:
|
||||
|
||||
// @todo, there needs to be a way of reporting the line number
|
||||
msg.Printf( wxT( "RS274X: Invalid primitive id code %d\n" ), prim.primitive_id );
|
||||
msg.Printf( wxT( "RS274X: Aperture Macro \"%s\": Invalid primitive id code %d, line: \"%s\"" ),
|
||||
GetChars(am.name), primitive_type, CONV_FROM_UTF8(buff) );
|
||||
ReportMessage( msg );
|
||||
return false;
|
||||
}
|
||||
|
||||
AM_PRIMITIVE prim( m_GerbMetric );
|
||||
prim.primitive_id = (AM_PRIMITIVE_ID) primitive_type;
|
||||
int i;
|
||||
for( i = 0; i < paramCount && *text != '*'; ++i )
|
||||
for( i = 0; i < paramCount && *text && *text != '*'; ++i )
|
||||
{
|
||||
prim.params.push_back( DCODE_PARAM() );
|
||||
|
||||
DCODE_PARAM& param = prim.params.back();
|
||||
|
||||
if( !CheckForLineEnd( buff, text, gerber_file ) )
|
||||
text = GetNextLine( buff, text, gerber_file );
|
||||
if( text == NULL) // End of File
|
||||
return false;
|
||||
|
||||
if( *text == '$' )
|
||||
{
|
||||
++text;
|
||||
param.SetIndex( ReadInt( text ) );
|
||||
}
|
||||
else
|
||||
param.SetValue( ReadDouble( text ) );
|
||||
ReadMacroParam( param, text );
|
||||
}
|
||||
|
||||
if( i < paramCount )
|
||||
|
@ -856,6 +935,7 @@ bool GERBER_IMAGE::ReadApertureMacro( char buff[GERBER_BUFZ],
|
|||
"RS274X: read macro descr type %d: read %d parameters, insufficient parameters\n" ),
|
||||
prim.primitive_id, i );
|
||||
ReportMessage( msg );
|
||||
|
||||
}
|
||||
// there are more parameters to read if this is an AMP_OUTLINE
|
||||
if( prim.primitive_id == AMP_OUTLINE )
|
||||
|
@ -875,16 +955,10 @@ bool GERBER_IMAGE::ReadApertureMacro( char buff[GERBER_BUFZ],
|
|||
|
||||
DCODE_PARAM& param = prim.params.back();
|
||||
|
||||
if( !CheckForLineEnd( buff, text, gerber_file ) )
|
||||
text = GetNextLine( buff, text, gerber_file );
|
||||
if( text == NULL ) // End of File
|
||||
return false;
|
||||
|
||||
if( *text == '$' )
|
||||
{
|
||||
++text;
|
||||
param.SetIndex( ReadInt( text ) );
|
||||
}
|
||||
else
|
||||
param.SetValue( ReadDouble( text ) );
|
||||
ReadMacroParam( param, text );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -895,3 +969,37 @@ 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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue