PDF plotter: better handling of non ASCII7 (unicode 16) chars.
Note also the PS plotter handle poorly these non ASCII chars. Fixes #4957 https://gitlab.com/kicad/code/kicad/issues/4957
This commit is contained in:
parent
6900f04ee0
commit
ed79ef8feb
|
@ -41,6 +41,70 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
std::string PDF_PLOTTER::encodeStringForPlotter( const wxString& aText )
|
||||||
|
{
|
||||||
|
// returns a string compatible with PDF string convention from a unicode string.
|
||||||
|
// if the initial text is only ASCII7, return the text between ( and ) for a good readability
|
||||||
|
// if the initial text is no ASCII7, return the text between < and >
|
||||||
|
// and encoded using 16 bits hexa (4 digits) by wide char (unicode 16)
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
// Is aText only ASCII7 ?
|
||||||
|
bool is_ascii7 = true;
|
||||||
|
|
||||||
|
for( size_t ii = 0; ii < aText.Len(); ii++ )
|
||||||
|
{
|
||||||
|
if( aText[ii] >= 0x7F )
|
||||||
|
{
|
||||||
|
is_ascii7 = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( is_ascii7 )
|
||||||
|
{
|
||||||
|
result = '(';
|
||||||
|
|
||||||
|
for( unsigned ii = 0; ii < aText.Len(); ii++ )
|
||||||
|
{
|
||||||
|
unsigned int code = aText[ii];
|
||||||
|
|
||||||
|
// These characters must be escaped
|
||||||
|
switch( code )
|
||||||
|
{
|
||||||
|
// se if '(' and ')' must be escaped.
|
||||||
|
case '\\':
|
||||||
|
result += '\\';
|
||||||
|
KI_FALLTHROUGH;
|
||||||
|
|
||||||
|
default:
|
||||||
|
result += code;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += ')';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = "<FEFF";
|
||||||
|
|
||||||
|
for( size_t ii = 0; ii < aText.Len(); ii++ )
|
||||||
|
{
|
||||||
|
unsigned int code = aText[ii];
|
||||||
|
char buffer[16];
|
||||||
|
sprintf( buffer, "%4.4X", code );
|
||||||
|
result += buffer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
result += '>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open or create the plot file aFullFilename
|
* Open or create the plot file aFullFilename
|
||||||
* return true if success, false if the file cannot be created/opened
|
* return true if success, false if the file cannot be created/opened
|
||||||
|
@ -749,14 +813,14 @@ bool PDF_PLOTTER::EndPlot()
|
||||||
|
|
||||||
fprintf( outputFile,
|
fprintf( outputFile,
|
||||||
"<<\n"
|
"<<\n"
|
||||||
"/Producer (KiCAD PDF)\n"
|
"/Producer (KiCad PDF)\n"
|
||||||
"/CreationDate (%s)\n"
|
"/CreationDate (%s)\n"
|
||||||
"/Creator (%s)\n"
|
"/Creator %s\n"
|
||||||
"/Title (%s)\n"
|
"/Title %s\n"
|
||||||
"/Trapped False\n",
|
"/Trapped False\n",
|
||||||
date_buf,
|
date_buf,
|
||||||
TO_UTF8( creator ),
|
encodeStringForPlotter( creator ).c_str(),
|
||||||
TO_UTF8( title ) );
|
encodeStringForPlotter( title ).c_str() );
|
||||||
|
|
||||||
fputs( ">>\n", outputFile );
|
fputs( ">>\n", outputFile );
|
||||||
closePdfObject();
|
closePdfObject();
|
||||||
|
@ -846,8 +910,8 @@ void PDF_PLOTTER::Text( const wxPoint& aPos,
|
||||||
fontname, heightFactor, render_mode, wideningFactor * 100 );
|
fontname, heightFactor, render_mode, wideningFactor * 100 );
|
||||||
|
|
||||||
// The text must be escaped correctly
|
// The text must be escaped correctly
|
||||||
fputsPostscriptString( workFile, aText );
|
std:: string txt_pdf = encodeStringForPlotter( aText );
|
||||||
fputs( " Tj ET\n", workFile );
|
fprintf( workFile, "%s Tj ET\n", txt_pdf.c_str() );
|
||||||
|
|
||||||
// Restore the CTM
|
// Restore the CTM
|
||||||
fputs( "Q\n", workFile );
|
fputs( "Q\n", workFile );
|
||||||
|
|
|
@ -300,16 +300,17 @@ void PSLIKE_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
std::string PSLIKE_PLOTTER::encodeStringForPlotter( const wxString& aUnicode )
|
||||||
* Write on a stream a string escaped for postscript/PDF
|
|
||||||
*/
|
|
||||||
void PSLIKE_PLOTTER::fputsPostscriptString(FILE *fout, const wxString& txt)
|
|
||||||
{
|
{
|
||||||
putc( '(', fout );
|
// Write on a std::string a string escaped for postscript/PDF
|
||||||
for( unsigned i = 0; i < txt.length(); i++ )
|
std::string converted;
|
||||||
|
|
||||||
|
converted += '(';
|
||||||
|
|
||||||
|
for( unsigned i = 0; i < aUnicode.Len(); i++ )
|
||||||
{
|
{
|
||||||
// Lazyness made me use stdio buffering yet another time...
|
// Lazyness made me use stdio buffering yet another time...
|
||||||
wchar_t ch = txt[i];
|
wchar_t ch = aUnicode[i];
|
||||||
|
|
||||||
if( ch < 256 )
|
if( ch < 256 )
|
||||||
{
|
{
|
||||||
|
@ -322,17 +323,19 @@ void PSLIKE_PLOTTER::fputsPostscriptString(FILE *fout, const wxString& txt)
|
||||||
case '(':
|
case '(':
|
||||||
case ')':
|
case ')':
|
||||||
case '\\':
|
case '\\':
|
||||||
putc( '\\', fout );
|
converted += '\\';
|
||||||
KI_FALLTHROUGH;
|
KI_FALLTHROUGH;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
putc( ch, fout );
|
converted += ch;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
putc( ')', fout );
|
converted += ')';
|
||||||
|
|
||||||
|
return converted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -871,7 +874,7 @@ bool PS_PLOTTER::StartPlot()
|
||||||
/* A "newline" character ("\n") is not included in the following string,
|
/* A "newline" character ("\n") is not included in the following string,
|
||||||
because it is provided by the ctime() function. */
|
because it is provided by the ctime() function. */
|
||||||
fprintf( outputFile, "%%%%CreationDate: %s", ctime( &time1970 ) );
|
fprintf( outputFile, "%%%%CreationDate: %s", ctime( &time1970 ) );
|
||||||
fprintf( outputFile, "%%%%Title: %s\n", TO_UTF8( filename ) );
|
fprintf( outputFile, "%%%%Title: %s\n", encodeStringForPlotter( title ).c_str() );
|
||||||
fprintf( outputFile, "%%%%Pages: 1\n" );
|
fprintf( outputFile, "%%%%Pages: 1\n" );
|
||||||
fprintf( outputFile, "%%%%PageOrder: Ascend\n" );
|
fprintf( outputFile, "%%%%PageOrder: Ascend\n" );
|
||||||
|
|
||||||
|
@ -991,9 +994,9 @@ void PS_PLOTTER::Text( const wxPoint& aPos,
|
||||||
// Draw the hidden postscript text (if requested)
|
// Draw the hidden postscript text (if requested)
|
||||||
if( m_textMode == PLOT_TEXT_MODE::PHANTOM )
|
if( m_textMode == PLOT_TEXT_MODE::PHANTOM )
|
||||||
{
|
{
|
||||||
fputsPostscriptString( outputFile, aText );
|
std::string ps_test = encodeStringForPlotter( aText );
|
||||||
DPOINT pos_dev = userToDeviceCoordinates( aPos );
|
DPOINT pos_dev = userToDeviceCoordinates( aPos );
|
||||||
fprintf( outputFile, " %g %g phantomshow\n", pos_dev.x, pos_dev.y );
|
fprintf( outputFile, "%s %g %g phantomshow\n", ps_test.c_str(), pos_dev.x, pos_dev.y );
|
||||||
}
|
}
|
||||||
|
|
||||||
PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aWidth,
|
PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aWidth,
|
||||||
|
|
|
@ -766,7 +766,10 @@ protected:
|
||||||
void postscriptOverlinePositions( const wxString& aText, int aXSize,
|
void postscriptOverlinePositions( const wxString& aText, int aXSize,
|
||||||
bool aItalic, bool aBold,
|
bool aItalic, bool aBold,
|
||||||
std::vector<int> *pos_pairs );
|
std::vector<int> *pos_pairs );
|
||||||
void fputsPostscriptString(FILE *fout, const wxString& txt);
|
|
||||||
|
/// convert a wxString unicode string to a char string compatible with the accepted
|
||||||
|
/// string plotter format (convert special chars and non ascii7 chars)
|
||||||
|
virtual std::string encodeStringForPlotter( const wxString& aUnicode );
|
||||||
|
|
||||||
/// Virtual primitive for emitting the setrgbcolor operator
|
/// Virtual primitive for emitting the setrgbcolor operator
|
||||||
virtual void emitSetRGBColor( double r, double g, double b ) = 0;
|
virtual void emitSetRGBColor( double r, double g, double b ) = 0;
|
||||||
|
@ -917,6 +920,10 @@ public:
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/// convert a wxString unicode string to a char string compatible with the accepted
|
||||||
|
/// string PDF format (convert special chars and non ascii7 chars)
|
||||||
|
std::string encodeStringForPlotter( const wxString& aUnicode ) override;
|
||||||
|
|
||||||
virtual void emitSetRGBColor( double r, double g, double b ) override;
|
virtual void emitSetRGBColor( double r, double g, double b ) override;
|
||||||
int allocPdfObject();
|
int allocPdfObject();
|
||||||
int startPdfObject(int handle = -1);
|
int startPdfObject(int handle = -1);
|
||||||
|
|
Loading…
Reference in New Issue