diff --git a/gerbview/job_file_reader.cpp b/gerbview/job_file_reader.cpp index abe8d0951a..ec4c19cae1 100644 --- a/gerbview/job_file_reader.cpp +++ b/gerbview/job_file_reader.cpp @@ -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; } - - diff --git a/pcbnew/board_stackup_manager/class_board_stackup.cpp b/pcbnew/board_stackup_manager/class_board_stackup.cpp index cff7df7366..37f5d29fa1 100644 --- a/pcbnew/board_stackup_manager/class_board_stackup.cpp +++ b/pcbnew/board_stackup_manager/class_board_stackup.cpp @@ -25,6 +25,7 @@ #include #include #include +#include // 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 ); } diff --git a/pcbnew/exporters/gerber_jobfile_writer.cpp b/pcbnew/exporters/gerber_jobfile_writer.cpp index 67f7ed6051..73c78ac484 100644 --- a/pcbnew/exporters/gerber_jobfile_writer.cpp +++ b/pcbnew/exporters/gerber_jobfile_writer.cpp @@ -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 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 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(); diff --git a/pcbnew/exporters/gerber_jobfile_writer.h b/pcbnew/exporters/gerber_jobfile_writer.h index 89033fbd73..7704b0e228 100644 --- a/pcbnew/exporters/gerber_jobfile_writer.h +++ b/pcbnew/exporters/gerber_jobfile_writer.h @@ -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)