Fix some issues in .gbrjob file.

2 issues are fixed: a missing double quote, and a incorrect handling of unicode chars

Fixes: lp:1836448
https://bugs.launchpad.net/kicad/+bug/1836448
This commit is contained in:
jean-pierre charras 2019-07-14 10:19:53 +02:00
parent be5f3717c7
commit fc2379ca8a
4 changed files with 69 additions and 27 deletions

View File

@ -1,8 +1,8 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2007-2017 Jean-Pierre Charras jp.charras at wanadoo.fr
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2007-2019 Jean-Pierre Charras jp.charras at wanadoo.fr
* Copyright (C) 1992-2019 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
@ -89,6 +89,11 @@ private:
REPORTER* m_reporter;
wxFileName m_filename;
wxArrayString m_GerberFiles; // List of gerber files in job
// Convert a JSON string, that uses escaped sequence of 4 hexdecimal digits
// to encode unicode chars when not ASCII7 codes
// json11 converts this sequence to UTF8 string
wxString formatStringFromJSON( const std::string& name );
};
@ -133,10 +138,8 @@ bool GERBER_JOBFILE_READER::ReadGerberJobFile()
for( auto& entry : json_parser["FilesAttributes"].array_items() )
{
//wxLogMessage( entry.dump().c_str() );
std::string name = entry["Path"].string_value();
//wxLogMessage( name.c_str() );
m_GerberFiles.Add( FormatStringFromGerber( name ) );
m_GerberFiles.Add( formatStringFromJSON( name ) );
}
}
else
@ -152,6 +155,18 @@ bool GERBER_JOBFILE_READER::ReadGerberJobFile()
}
wxString GERBER_JOBFILE_READER::formatStringFromJSON( const std::string& name )
{
// Convert a JSON string, that uses a escaped sequence of 4 hexdecimal digits
// to encode unicode chars
// Our json11 library returns in this case a UTF8 sequence. Just convert it to
// a wxString.
wxString wstr = FROM_UTF8( name.c_str() );
return wstr;
}
bool GERBVIEW_FRAME::LoadGerberJobFile( const wxString& aFullFileName )
{
wxFileName filename = aFullFileName;
@ -221,5 +236,3 @@ bool GERBVIEW_FRAME::LoadGerberJobFile( const wxString& aFullFileName )
return success;
}

View File

@ -25,6 +25,7 @@
#include <layers_id_colors_and_visibility.h>
#include <board_design_settings.h>
#include <class_board.h>
#include <i18n_utility.h> // For _HKI definition
#include "stackup_predefined_prms.h"
// A reasonable thickness for copper layers:
@ -310,6 +311,9 @@ bool BOARD_STACKUP::SynchronizeWithBoard( BOARD_DESIGN_SETTINGS* aSettings )
void BOARD_STACKUP::BuildDefaultStackupList( BOARD_DESIGN_SETTINGS* aSettings )
{
// Creates a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
// Note: the m_TypeName string is made translatable using _HKI marker, but is not
// translated when building the stackup.
// It will be used as this in files, and can be translated only in dialog
LSET enabledLayer = aSettings->GetEnabledLayers();
int copperLayerCount = aSettings->GetCopperLayerCount();
double diel_thickness = aSettings->GetBoardThickness()
@ -323,7 +327,7 @@ void BOARD_STACKUP::BuildDefaultStackupList( BOARD_DESIGN_SETTINGS* aSettings )
{
BOARD_STACKUP_ITEM* item = new BOARD_STACKUP_ITEM( BS_ITEM_TYPE_SILKSCREEN );
item->m_LayerId = F_SilkS;
item->m_TypeName = _( "Top Silk Screen" );
item->m_TypeName = _HKI( "Top Silk Screen" );
Add( item );
}
@ -331,7 +335,7 @@ void BOARD_STACKUP::BuildDefaultStackupList( BOARD_DESIGN_SETTINGS* aSettings )
{
BOARD_STACKUP_ITEM* item = new BOARD_STACKUP_ITEM( BS_ITEM_TYPE_SOLDERPASTE );
item->m_LayerId = F_Paste;
item->m_TypeName = _( "Top Solder Paste" );
item->m_TypeName = _HKI( "Top Solder Paste" );
Add( item );
}
@ -339,7 +343,7 @@ void BOARD_STACKUP::BuildDefaultStackupList( BOARD_DESIGN_SETTINGS* aSettings )
{
BOARD_STACKUP_ITEM* item = new BOARD_STACKUP_ITEM( BS_ITEM_TYPE_SOLDERMASK );
item->m_LayerId = F_Mask;
item->m_TypeName = _( "Top Solder Mask" );
item->m_TypeName = _HKI( "Top Solder Mask" );
Add( item );
}
@ -364,12 +368,12 @@ void BOARD_STACKUP::BuildDefaultStackupList( BOARD_DESIGN_SETTINGS* aSettings )
// Display a dielectric default layer name:
if( (dielectric_idx & 1) == 0 )
{
item->m_TypeName = _( "core" );
item->m_TypeName = _HKI( "core" );
item->m_Material = "FR4";
}
else
{
item->m_TypeName = _( "prepreg" );
item->m_TypeName = _HKI( "prepreg" );
item->m_Material = "FR4";
}
@ -382,7 +386,7 @@ void BOARD_STACKUP::BuildDefaultStackupList( BOARD_DESIGN_SETTINGS* aSettings )
{
BOARD_STACKUP_ITEM* item = new BOARD_STACKUP_ITEM( BS_ITEM_TYPE_SOLDERMASK );
item->m_LayerId = B_Mask;
item->m_TypeName = _( "Bottom Solder Mask" );
item->m_TypeName = _HKI( "Bottom Solder Mask" );
Add( item );
}
@ -390,7 +394,7 @@ void BOARD_STACKUP::BuildDefaultStackupList( BOARD_DESIGN_SETTINGS* aSettings )
{
BOARD_STACKUP_ITEM* item = new BOARD_STACKUP_ITEM( BS_ITEM_TYPE_SOLDERPASTE );
item->m_LayerId = B_Paste;
item->m_TypeName = _( "Bottom Solder Paste" );
item->m_TypeName = _HKI( "Bottom Solder Paste" );
Add( item );
}
@ -398,7 +402,7 @@ void BOARD_STACKUP::BuildDefaultStackupList( BOARD_DESIGN_SETTINGS* aSettings )
{
BOARD_STACKUP_ITEM* item = new BOARD_STACKUP_ITEM( BS_ITEM_TYPE_SILKSCREEN );
item->m_LayerId = B_SilkS;
item->m_TypeName = _( "Bottom Silk Screen" );
item->m_TypeName = _HKI( "Bottom Silk Screen" );
Add( item );
}

View File

@ -56,6 +56,25 @@ GERBER_JOBFILE_WRITER::GERBER_JOBFILE_WRITER( BOARD* aPcb, REPORTER* aReporter )
m_indent = 0;
}
std::string GERBER_JOBFILE_WRITER::formatStringFromUTF32( const wxString& aText )
{
std::string fmt_text; // the text after UTF32 to UTF8 conversion
for( unsigned long letter: aText )
{
if( letter >= ' ' && letter <= 0x7F )
fmt_text += char( letter );
else
{
char buff[10];
sprintf( buff, "\\u%4.4lX", letter );
fmt_text += buff;
}
}
return fmt_text;
}
enum ONSIDE GERBER_JOBFILE_WRITER::hasSilkLayers()
{
int flag = SIDE_NONE;
@ -249,7 +268,7 @@ void GERBER_JOBFILE_WRITER::addJSONGeneralSpecs()
wxString guid = GbrMakeProjectGUIDfromString( msg );
// build the <project id> string: this is the board short filename (without ext)
// and all non ASCII chars are replaced by '_'
// and all non ASCII chars are replaced by '_', to be compatible with .gbr files.
msg = fn.GetName();
// build the <rec> string. All non ASCII chars and comma are replaced by '_'
@ -421,9 +440,8 @@ void GERBER_JOBFILE_WRITER::addJSONFilesAttributes()
if( !skip_file )
{
// name can contain non ASCII7 chars.
// Only ASCII7 chars are accepted in gerber files. others must be converted to
// a gerber hexa sequence.
std::string strname = formatStringToGerber( name );
// Ensure the name is JSON compatible.
std::string strname = formatStringFromUTF32( name );
openBlock();
addJSONObject( wxString::Format( "\"Path\": \"%s\",\n", strname.c_str() ) );
@ -604,28 +622,28 @@ void GERBER_JOBFILE_WRITER::addJSONMaterialStackup()
{
case BS_ITEM_TYPE_COPPER:
layer_type = "Copper";
layer_name = formatStringToGerber( m_pcb->GetLayerName( item->m_LayerId ) );
layer_name = formatStringFromUTF32( m_pcb->GetLayerName( item->m_LayerId ) );
last_copper_layer = item->m_LayerId;
break;
case BS_ITEM_TYPE_SILKSCREEN:
layer_type = "Legend";
layer_name = formatStringToGerber( item->m_TypeName );
layer_name = formatStringFromUTF32( item->m_TypeName );
break;
case BS_ITEM_TYPE_SOLDERMASK:
layer_type = "SolderMask";
layer_name = formatStringToGerber( item->m_TypeName );
layer_name = formatStringFromUTF32( item->m_TypeName );
break;
case BS_ITEM_TYPE_SOLDERPASTE:
layer_type = "SolderPaste";
layer_name = formatStringToGerber( item->m_TypeName );
layer_name = formatStringFromUTF32( item->m_TypeName );
break;
case BS_ITEM_TYPE_DIELECTRIC:
layer_type = "Dielectric";
layer_name = formatStringToGerber( wxString::Format( "dielectric layer %d (%s)",
layer_name = formatStringFromUTF32( wxString::Format( "dielectric layer %d (%s)",
item->m_DielectricLayerId, item->m_TypeName ) );
break;
@ -670,14 +688,16 @@ void GERBER_JOBFILE_WRITER::addJSONMaterialStackup()
if( uptodate ) // We can add the dielectric variant ("core" "prepreg" ...):
note << wxString::Format( " \"Type: %s", layer_name.c_str() );
note << wxString::Format( " (from %s to %s)\"\n",
formatStringToGerber( m_pcb->GetLayerName( last_copper_layer ) ),
formatStringToGerber( m_pcb->GetLayerName( next_copper_layer ) ) );
note << wxString::Format( " \"(from %s to %s)\"\n",
formatStringFromUTF32( m_pcb->GetLayerName( last_copper_layer ) ),
formatStringFromUTF32( m_pcb->GetLayerName( next_copper_layer ) ) );
addJSONObject( note );
}
else
{
addJSONObject( wxString::Format( "\"Notes\": \"Layer: %s\",\n", layer_name.c_str() ) );
}
removeJSONSepararator();
closeBlockWithSep();

View File

@ -202,6 +202,11 @@ private:
addIndent(); m_JSONbuffer << aParam;
}
/** A helper function to convert a wxString ( therefore a Unicode text ) to
* a JSON compatible string (a escaped unicode sequence of 4 hexa).
*/
std::string formatStringFromUTF32( const wxString& aText );
private:
BOARD* m_pcb; // The board
REPORTER* m_reporter; // a reporter for messages (can be null)