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;
|
||||
}
|
||||
|
||||
|
||||
// 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 )
|
||||
{
|
||||
// make the inverse conversion of formatStringToGerber()
|
||||
// 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
|
||||
// Note the initial gerber string can already contain unicode chars.
|
||||
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];
|
||||
|
||||
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)
|
||||
// If an error occurs, the escape sequence is not translated,
|
||||
// and used "as this"
|
||||
long value = 0;
|
||||
bool error = false;
|
||||
|
||||
for( int jj = 0; jj < 4; jj++ )
|
||||
{
|
||||
value <<= 4;
|
||||
code = aString[++ii];
|
||||
// Very basic conversion, but it expects a valid gerber file
|
||||
int hexa = (code <= '9' ? code - '0' : code - 'A' + 10) & 0xF;
|
||||
value += hexa;
|
||||
code = aString[ii+jj+2];
|
||||
|
||||
int hexa = char2Hex( code );
|
||||
|
||||
if( hexa >= 0 )
|
||||
value += hexa;
|
||||
else
|
||||
{
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
txt.Append( wxChar( value ) );
|
||||
if( !error )
|
||||
{
|
||||
if( value >= ' ' ) // Is a valid wxChar ?
|
||||
txt.Append( wxChar( value ) );
|
||||
|
||||
ii += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
txt.Append( aString[ii] );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
txt.Append( aString[ii] );
|
||||
|
@ -334,12 +379,10 @@ std::string formatStringToGerber( const wxString& aString )
|
|||
|
||||
if( convert || code > 0x7F )
|
||||
{
|
||||
txt += '\\';
|
||||
|
||||
// Convert code to 4 hexadecimal digit
|
||||
// (Gerber allows only 4 hexadecimal digit)
|
||||
char hexa[32];
|
||||
sprintf( hexa,"%4.4X", code & 0xFFFF);
|
||||
sprintf( hexa,"\\u%4.4X", code & 0xFFFF);
|
||||
txt += hexa;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <gerbview.h>
|
||||
#include <gerber_file_image.h>
|
||||
#include <X2_gerber_attributes.h>
|
||||
#include <gbr_metadata.h>
|
||||
|
||||
extern int ReadInt( 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 )
|
||||
{
|
||||
|
@ -451,18 +408,18 @@ bool GERBER_FILE_IMAGE::ExecuteRS274XCommand( int aCommand, char* aBuff,
|
|||
if( dummy.GetAttribute() == ".N" )
|
||||
{
|
||||
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" )
|
||||
{
|
||||
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" )
|
||||
{
|
||||
m_NetAttributeDict.m_NetAttribType |= GBR_NETLIST_METADATA::GBR_NETINFO_PAD;
|
||||
m_NetAttributeDict.m_Cmpref = fromGerberString( dummy.GetPrm( 1 ) );
|
||||
m_NetAttributeDict.m_Padname = fromGerberString( dummy.GetPrm( 2 ) );
|
||||
m_NetAttributeDict.m_Cmpref = FormatStringFromGerber( dummy.GetPrm( 1 ) );
|
||||
m_NetAttributeDict.m_Padname = FormatStringFromGerber( dummy.GetPrm( 2 ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue