Gerber files: update unicode coding to the 2019 06 Gerber specifications.
In gbr files, not allowed chars are coded using a 16 bit (4 hexa digits) unicode sequence. Previously, it was \XXXX and now is \uXXXX escape sequence. Changes from master branch.
This commit is contained in:
parent
7f1c7d808d
commit
8c03d1bdde
|
@ -268,33 +268,78 @@ std::string GBR_APERTURE_METADATA::FormatAttribute( GBR_APERTURE_ATTRIB aAttribu
|
||||||
return full_attribute_string;
|
return full_attribute_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function to convert a ascii hex char to its integer value
|
||||||
|
// If the char is not a hexa char, return -1
|
||||||
|
int char2Hex( unsigned aCode )
|
||||||
|
{
|
||||||
|
if( aCode >= '0' && aCode <= '9' )
|
||||||
|
return aCode - '0';
|
||||||
|
|
||||||
|
if( aCode >= 'A' && aCode <= 'F' )
|
||||||
|
return aCode - 'A' + 10;
|
||||||
|
|
||||||
|
if( aCode >= 'a' && aCode <= 'f' )
|
||||||
|
return aCode - 'a' + 10;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
wxString FormatStringFromGerber( const wxString& aString )
|
wxString FormatStringFromGerber( const wxString& aString )
|
||||||
{
|
{
|
||||||
// make the inverse conversion of formatStringToGerber()
|
// make the inverse conversion of formatStringToGerber()
|
||||||
// It converts a "normalized" gerber string and convert it to a 16 bits sequence unicode
|
// It converts a "normalized" gerber string and convert it to a 16 bits sequence unicode
|
||||||
// and return a wxString (unicode 16) from the gerber string
|
// and return a wxString (unicode 16) from the gerber string
|
||||||
|
// Note the initial gerber string can already contain unicode chars.
|
||||||
wxString txt;
|
wxString txt;
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < aString.Length(); ++ii )
|
unsigned count = aString.Length();
|
||||||
|
|
||||||
|
for( unsigned ii = 0; ii < count; ++ii )
|
||||||
{
|
{
|
||||||
unsigned code = aString[ii];
|
unsigned code = aString[ii];
|
||||||
|
|
||||||
if( code == '\\' )
|
if( code == '\\' && ii < count-5 && aString[ii+1] == 'u' )
|
||||||
{
|
{
|
||||||
// Convert 4 hexadecimal digits to a 16 bit unicode
|
// Note the latest Gerber X2 spec (2019 06) uses \uXXXX to encode
|
||||||
|
// the unicode XXXX hexadecimal value
|
||||||
|
// If 4 chars next to 'u' are hexadecimal chars,
|
||||||
|
// convert these 4 hexadecimal digits to a 16 bit unicode
|
||||||
// (Gerber allows only 4 hexadecimal digits)
|
// (Gerber allows only 4 hexadecimal digits)
|
||||||
|
// If an error occurs, the escape sequence is not translated,
|
||||||
|
// and used "as this"
|
||||||
long value = 0;
|
long value = 0;
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
for( int jj = 0; jj < 4; jj++ )
|
for( int jj = 0; jj < 4; jj++ )
|
||||||
{
|
{
|
||||||
value <<= 4;
|
value <<= 4;
|
||||||
code = aString[++ii];
|
code = aString[ii+jj+2];
|
||||||
// Very basic conversion, but it expects a valid gerber file
|
|
||||||
int hexa = (code <= '9' ? code - '0' : code - 'A' + 10) & 0xF;
|
int hexa = char2Hex( code );
|
||||||
|
|
||||||
|
if( hexa >= 0 )
|
||||||
value += hexa;
|
value += hexa;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !error )
|
||||||
|
{
|
||||||
|
if( value >= ' ' ) // Is a valid wxChar ?
|
||||||
txt.Append( wxChar( value ) );
|
txt.Append( wxChar( value ) );
|
||||||
|
|
||||||
|
ii += 5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
txt.Append( aString[ii] );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
txt.Append( aString[ii] );
|
txt.Append( aString[ii] );
|
||||||
|
@ -334,12 +379,10 @@ std::string formatStringToGerber( const wxString& aString )
|
||||||
|
|
||||||
if( convert || code > 0x7F )
|
if( convert || code > 0x7F )
|
||||||
{
|
{
|
||||||
txt += '\\';
|
|
||||||
|
|
||||||
// Convert code to 4 hexadecimal digit
|
// Convert code to 4 hexadecimal digit
|
||||||
// (Gerber allows only 4 hexadecimal digit)
|
// (Gerber allows only 4 hexadecimal digit)
|
||||||
char hexa[32];
|
char hexa[32];
|
||||||
sprintf( hexa,"%4.4X", code & 0xFFFF);
|
sprintf( hexa,"\\u%4.4X", code & 0xFFFF);
|
||||||
txt += hexa;
|
txt += hexa;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <gerbview.h>
|
#include <gerbview.h>
|
||||||
#include <gerber_file_image.h>
|
#include <gerber_file_image.h>
|
||||||
#include <X2_gerber_attributes.h>
|
#include <X2_gerber_attributes.h>
|
||||||
|
#include <gbr_metadata.h>
|
||||||
|
|
||||||
extern int ReadInt( char*& text, bool aSkipSeparator = true );
|
extern int ReadInt( char*& text, bool aSkipSeparator = true );
|
||||||
extern double ReadDouble( char*& text, bool aSkipSeparator = true );
|
extern double ReadDouble( char*& text, bool aSkipSeparator = true );
|
||||||
|
@ -138,50 +139,6 @@ int GERBER_FILE_IMAGE::ReadXCommandID( char*& text )
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a string read from a gerber file to an unicode string
|
|
||||||
* Usual chars (ASCII7 values) are the only values allowed in Gerber files,
|
|
||||||
* and are just copied.
|
|
||||||
* However Gerber format allows using non ASCII7 values by coding them in a
|
|
||||||
* sequence of 4 hexadecimal chars (16 bits hexadecimal value)
|
|
||||||
* Hexadecimal coded values ("\hhhh") are converted to
|
|
||||||
* the unicode char value
|
|
||||||
*/
|
|
||||||
static const wxString fromGerberString( const wxString& aGbrString )
|
|
||||||
{
|
|
||||||
wxString text;
|
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < aGbrString.size(); ++ii )
|
|
||||||
{
|
|
||||||
if( aGbrString[ii] == '\\' )
|
|
||||||
{
|
|
||||||
unsigned value = 0;
|
|
||||||
|
|
||||||
for( int jj = 0; jj < 4; jj++ )
|
|
||||||
{ // Convert 4 hexa digits to binary value:
|
|
||||||
ii++;
|
|
||||||
value <<= 4;
|
|
||||||
int digit = aGbrString[ii];
|
|
||||||
|
|
||||||
if( digit >= '0' && digit <= '9' )
|
|
||||||
digit -= '0';
|
|
||||||
else if( digit >= 'A' && digit <= 'F' )
|
|
||||||
digit -= 'A' - 10;
|
|
||||||
else if( digit >= 'a' && digit <= 'f' )
|
|
||||||
digit -= 'a' - 10;
|
|
||||||
else digit = 0;
|
|
||||||
|
|
||||||
value += digit & 0xF;
|
|
||||||
}
|
|
||||||
|
|
||||||
text.Append( wxUniChar( value ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
text.Append( aGbrString[ii] );
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GERBER_FILE_IMAGE::ReadRS274XCommand( char *aBuff, unsigned int aBuffSize, char*& aText )
|
bool GERBER_FILE_IMAGE::ReadRS274XCommand( char *aBuff, unsigned int aBuffSize, char*& aText )
|
||||||
{
|
{
|
||||||
|
@ -451,18 +408,18 @@ bool GERBER_FILE_IMAGE::ExecuteRS274XCommand( int aCommand, char* aBuff,
|
||||||
if( dummy.GetAttribute() == ".N" )
|
if( dummy.GetAttribute() == ".N" )
|
||||||
{
|
{
|
||||||
m_NetAttributeDict.m_NetAttribType |= GBR_NETLIST_METADATA::GBR_NETINFO_NET;
|
m_NetAttributeDict.m_NetAttribType |= GBR_NETLIST_METADATA::GBR_NETINFO_NET;
|
||||||
m_NetAttributeDict.m_Netname = fromGerberString( dummy.GetPrm( 1 ) );
|
m_NetAttributeDict.m_Netname = FormatStringFromGerber( dummy.GetPrm( 1 ) );
|
||||||
}
|
}
|
||||||
else if( dummy.GetAttribute() == ".C" )
|
else if( dummy.GetAttribute() == ".C" )
|
||||||
{
|
{
|
||||||
m_NetAttributeDict.m_NetAttribType |= GBR_NETLIST_METADATA::GBR_NETINFO_CMP;
|
m_NetAttributeDict.m_NetAttribType |= GBR_NETLIST_METADATA::GBR_NETINFO_CMP;
|
||||||
m_NetAttributeDict.m_Cmpref = fromGerberString( dummy.GetPrm( 1 ) );
|
m_NetAttributeDict.m_Cmpref = FormatStringFromGerber( dummy.GetPrm( 1 ) );
|
||||||
}
|
}
|
||||||
else if( dummy.GetAttribute() == ".P" )
|
else if( dummy.GetAttribute() == ".P" )
|
||||||
{
|
{
|
||||||
m_NetAttributeDict.m_NetAttribType |= GBR_NETLIST_METADATA::GBR_NETINFO_PAD;
|
m_NetAttributeDict.m_NetAttribType |= GBR_NETLIST_METADATA::GBR_NETINFO_PAD;
|
||||||
m_NetAttributeDict.m_Cmpref = fromGerberString( dummy.GetPrm( 1 ) );
|
m_NetAttributeDict.m_Cmpref = FormatStringFromGerber( dummy.GetPrm( 1 ) );
|
||||||
m_NetAttributeDict.m_Padname = fromGerberString( dummy.GetPrm( 2 ) );
|
m_NetAttributeDict.m_Padname = FormatStringFromGerber( dummy.GetPrm( 2 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue