Pcbnew, Gerber output: fix incorrect UUID format in %TF.ProjectId attribute.
Fixes: lp:1800459 https://bugs.launchpad.net/kicad/+bug/1800459
This commit is contained in:
parent
36bb92f844
commit
4daaaa373c
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -276,99 +276,82 @@ static wxString& makeStringCompatX1( wxString& aText, bool aUseX1CompatibilityMo
|
|||
}
|
||||
|
||||
|
||||
void BuildGerberX2Header( const BOARD *aBoard, wxArrayString& aHeader )
|
||||
/** A helper function to build a project GUID using format RFC4122 Version 1 or 4
|
||||
* from the project name, because a kicad project has no specific GUID
|
||||
* RFC4122 is used mainly for its syntax, because fields have no meaning for Gerber files
|
||||
* and therefore the GUID generated has no meaning because it do not use any time and time stamp
|
||||
* specific to the project, just a random pattern (random is here a pattern specific to a project).
|
||||
*
|
||||
* See en.wikipedia.org/wiki/Universally_unique_identifier
|
||||
*/
|
||||
static wxString makeProjectGUIDfromString( wxString& aText )
|
||||
{
|
||||
wxString text;
|
||||
// Gerber GUID format should be RFC4122 Version 1 or 4. The format is:
|
||||
// xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
|
||||
// with
|
||||
// x = hexDigit lower/upper case
|
||||
// and
|
||||
// M = '1' or '4' (UUID version: 1 (basic) or 4 (random)) (we use 4: UUID random)
|
||||
// and
|
||||
// N = '8' or '9' or 'A|a' or 'B|b' : UUID variant 1: 2 MSB bits have meaning) (we use N = 9)
|
||||
// N = 1000 or 1001 or 1010 or 1011 : 10xx means Variant 1 (Variant2: 110x and 111x are reserved)
|
||||
|
||||
// Creates the TF,.GenerationSoftware. Format is:
|
||||
// %TF,.GenerationSoftware,<vendor>,<application name>[,<application version>]*%
|
||||
text.Printf( wxT( "%%TF.GenerationSoftware,KiCad,Pcbnew,%s*%%" ), GetBuildVersion() );
|
||||
aHeader.Add( text );
|
||||
|
||||
// creates the TF.CreationDate ext:
|
||||
// The attribute value must conform to the full version of the ISO 8601
|
||||
// date and time format, including time and time zone. Note that this is
|
||||
// the date the Gerber file was effectively created,
|
||||
// not the time the project of PCB was started
|
||||
wxDateTime date( wxDateTime::GetTimeNow() );
|
||||
// Date format: see http://www.cplusplus.com/reference/ctime/strftime
|
||||
wxString msg = date.Format( wxT( "%z" ) ); // Extract the time zone offset
|
||||
// The time zone offset format is + (or -) mm or hhmm (mm = number of minutes, hh = number of hours)
|
||||
// we want +(or -) hh:mm
|
||||
if( msg.Len() > 3 )
|
||||
msg.insert( 3, ":", 1 ),
|
||||
text.Printf( wxT( "%%TF.CreationDate,%s%s*%%" ), GetChars( date.FormatISOCombined() ), GetChars( msg ) );
|
||||
aHeader.Add( text );
|
||||
|
||||
// Creates the TF,.ProjectId. Format is (from Gerber file format doc):
|
||||
// %TF.ProjectId,<project id>,<project GUID>,<revision id>*%
|
||||
// <project id> is the name of the project, restricted to basic ASCII symbols only,
|
||||
// and comma not accepted
|
||||
// All illegal chars will be replaced by underscore
|
||||
// <project GUID> is a 32 hexadecimal digits string which is an unique id of a project.
|
||||
// This is a random 128-bit number expressed in 32 hexadecimal digits.
|
||||
// See en.wikipedia.org/wiki/GUID for more information
|
||||
// However Kicad does not handle such a project GUID, so it is built from the board name
|
||||
// Rem: <project id> accepts only ASCII 7 code (only basic ASCII codes are allowed in gerber files).
|
||||
wxFileName fn = aBoard->GetFileName();
|
||||
msg = fn.GetFullName();
|
||||
wxString guid;
|
||||
|
||||
// Build a 32 digits GUID from the board name:
|
||||
for( unsigned ii = 0; ii < msg.Len(); ii++ )
|
||||
{
|
||||
int cc1 = int( msg[ii] ) & 0x0F;
|
||||
int cc2 = ( int( msg[ii] ) >> 4) & 0x0F;
|
||||
guid << wxString::Format( wxT( "%X%X" ), cc2, cc1 );
|
||||
|
||||
if( guid.Len() >= 32 )
|
||||
break;
|
||||
}
|
||||
|
||||
// guid has 32 digits, so add missing digits
|
||||
int cnt = 32 - guid.Len();
|
||||
// guid has 32 digits, so add chars in name to be sure we can build a 32 digits guid
|
||||
// (i.e. from a 16 char string name)
|
||||
// In fact only 30 digits are used, and 2 UID id
|
||||
wxString bname = aText;
|
||||
int cnt = 16 - bname.Len();
|
||||
|
||||
if( cnt > 0 )
|
||||
guid.Append( '0', cnt );
|
||||
bname.Append( 'X', cnt );
|
||||
|
||||
// build the <project id> string: this is the board short filename (without ext)
|
||||
// and all non ASCII chars and comma are replaced by '_'
|
||||
msg = fn.GetName();
|
||||
msg.Replace( wxT( "," ), wxT( "_" ) );
|
||||
int chr_idx = 0;
|
||||
|
||||
// build the <rec> string. All non ASCII chars and comma are replaced by '_'
|
||||
wxString rev = ((BOARD*)aBoard)->GetTitleBlock().GetRevision();
|
||||
rev.Replace( wxT( "," ), wxT( "_" ) );
|
||||
// Output the 8 first hex digits:
|
||||
for( unsigned ii = 0; ii < 4; ii++ )
|
||||
{
|
||||
int cc = int( bname[chr_idx++] ) & 0xFF;
|
||||
guid << wxString::Format( "%2.2x", cc );
|
||||
}
|
||||
|
||||
if( rev.IsEmpty() )
|
||||
rev = wxT( "rev?" );
|
||||
// Output the 4 next hex digits:
|
||||
guid << '-';
|
||||
|
||||
text.Printf( wxT( "%%TF.ProjectId,%s,%s,%s*%%" ), msg.ToAscii(), GetChars( guid ), rev.ToAscii() );
|
||||
aHeader.Add( text );
|
||||
for( unsigned ii = 0; ii < 2; ii++ )
|
||||
{
|
||||
int cc = int( bname[chr_idx++] ) & 0xFF;
|
||||
guid << wxString::Format( "%2.2x", cc );
|
||||
}
|
||||
|
||||
// Add the TF.SameCoordinates, that specify all gerber files uses the same
|
||||
// origin and orientation, and the registration between files is OK.
|
||||
// The parameter of TF.SameCoordinates is a string that is common
|
||||
// to all files using the same registration and has no special meaning:
|
||||
// this is just a key
|
||||
// Because there is no mirroring/rotation in Kicad, only the plot offset origin
|
||||
// can create incorrect registration.
|
||||
// So we create a key from plot offset options.
|
||||
// and therefore for a given board, all Gerber files having the same key have the same
|
||||
// plot origin and use the same registration
|
||||
//
|
||||
// Currently the key is "Original" when using absolute Pcbnew coordinates,
|
||||
// and te PY ans PY position od auxiliary axis, when using it.
|
||||
// Please, if absolute Pcbnew coordinates, one day, are set by user, change the way
|
||||
// the key is built to ensure file only using the *same* axis have the same key.
|
||||
wxString registration_id = "Original";
|
||||
wxPoint auxOrigin = aBoard->GetAuxOrigin();
|
||||
// Output the 4 next hex digits (UUID version and 3 digits):
|
||||
guid << "-4"; // first digit: UUID version 4 (M = 4)
|
||||
{
|
||||
int cc = int( bname[chr_idx++] ) << 4 & 0xFF0;
|
||||
cc += int( bname[chr_idx] ) >> 4 & 0x0F;
|
||||
guid << wxString::Format( "%3.3x", cc );
|
||||
}
|
||||
|
||||
if( aBoard->GetPlotOptions().GetUseAuxOrigin() && auxOrigin.x && auxOrigin.y )
|
||||
registration_id.Printf( "PX%xPY%x", auxOrigin.x, auxOrigin.y );
|
||||
// Output the 4 next hex digits (UUID variant and 3 digits):
|
||||
guid << "-9"; // first digit: UUID variant 1 (N = 9)
|
||||
{
|
||||
int cc = (int( bname[chr_idx++] ) & 0x0F) << 8;
|
||||
cc += int( bname[chr_idx++] ) & 0xFF;
|
||||
guid << wxString::Format( "%3.3x", cc );
|
||||
}
|
||||
|
||||
text.Printf( "%%TF.SameCoordinates,%s*%%", registration_id.GetData() );
|
||||
aHeader.Add( text );
|
||||
// Output the 12 last hex digits:
|
||||
guid << '-';
|
||||
|
||||
for( unsigned ii = 0; ii < 6; ii++ )
|
||||
{
|
||||
int cc = int( bname[chr_idx++] ) & 0xFF;
|
||||
guid << wxString::Format( "%2.2x", cc );
|
||||
}
|
||||
|
||||
return guid;
|
||||
}
|
||||
|
||||
|
||||
|
@ -400,33 +383,17 @@ void AddGerberX2Header( PLOTTER * aPlotter,
|
|||
// Creates the TF,.ProjectId. Format is (from Gerber file format doc):
|
||||
// %TF.ProjectId,<project id>,<project GUID>,<revision id>*%
|
||||
// <project id> is the name of the project, restricted to basic ASCII symbols only,
|
||||
// Rem: <project id> accepts only ASCII 7 code (only basic ASCII codes are allowed in gerber files).
|
||||
// and comma not accepted
|
||||
// All illegal chars will be replaced by underscore
|
||||
// <project GUID> is a 32 hexadecimal digits string which is an unique id of a project.
|
||||
// This is a random 128-bit number expressed in 32 hexadecimal digits.
|
||||
// See en.wikipedia.org/wiki/GUID for more information
|
||||
//
|
||||
// <project GUID> is a string which is an unique id of a project.
|
||||
// However Kicad does not handle such a project GUID, so it is built from the board name
|
||||
// Rem: <project id> accepts only ASCII 7 code (only basic ASCII codes are allowed in gerber files).
|
||||
wxFileName fn = aBoard->GetFileName();
|
||||
msg = fn.GetFullName();
|
||||
wxString guid;
|
||||
|
||||
// Build a 32 digits GUID from the board name:
|
||||
for( unsigned ii = 0; ii < msg.Len(); ii++ )
|
||||
{
|
||||
int cc1 = int( msg[ii] ) & 0x0F;
|
||||
int cc2 = ( int( msg[ii] ) >> 4) & 0x0F;
|
||||
guid << wxString::Format( wxT( "%X%X" ), cc2, cc1 );
|
||||
|
||||
if( guid.Len() >= 32 )
|
||||
break;
|
||||
}
|
||||
|
||||
// guid has 32 digits, so add missing digits
|
||||
int cnt = 32 - guid.Len();
|
||||
|
||||
if( cnt > 0 )
|
||||
guid.Append( '0', cnt );
|
||||
// Build a <project GUID>, from the board name
|
||||
wxString guid = makeProjectGUIDfromString( msg );
|
||||
|
||||
// build the <project id> string: this is the board short filename (without ext)
|
||||
// and all non ASCII chars and comma are replaced by '_'
|
||||
|
|
Loading…
Reference in New Issue