From c7f0ee3bd0f7d2fe657f4fa7e04f420b877a6542 Mon Sep 17 00:00:00 2001 From: Manolo Gouy Date: Mon, 8 Sep 2014 12:35:23 +0000 Subject: Fix for STR #3130 where PostScript printing may fail when program modifies LC_NUMERIC of its locale. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10290 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- src/Fl_PostScript.cxx | 94 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 38 deletions(-) (limited to 'src/Fl_PostScript.cxx') diff --git a/src/Fl_PostScript.cxx b/src/Fl_PostScript.cxx index 080f2a5c4..2bcde7a7a 100644 --- a/src/Fl_PostScript.cxx +++ b/src/Fl_PostScript.cxx @@ -23,6 +23,7 @@ #include #include #include +#include #if defined(USE_X11) #include "Fl_Font.H" #if USE_XFT @@ -139,6 +140,24 @@ Fl_PostScript_File_Device::~Fl_PostScript_File_Device() { if (ps) delete ps; } +/** Shields output PostScript data from modifications of the current locale. + It typically avoids PostScript errors caused if the current locale uses comma instead of dot + as "decimal point". + \param format directives controlling output PostScript data + \return value returned by vfprintf() call + */ +int Fl_PostScript_Graphics_Driver::clocale_printf(const char *format, ...) +{ + char *saved_locale = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC, "C"); + va_list args; + va_start(args, format); + int retval = vfprintf(output, format, args); + va_end(args); + setlocale(LC_NUMERIC, saved_locale); + return retval; +} + #ifndef FL_DOXYGEN #if ! (defined(__APPLE__) || defined(WIN32) ) @@ -654,7 +673,7 @@ void Fl_PostScript_Graphics_Driver::page(double pw, double ph, int media) { fprintf(output, "save\n"); fprintf(output, "GS\n"); - fprintf(output, "%g %g TR\n", (double)0 /*lm_*/ , ph_ /* - tm_*/); + clocale_printf( "%g %g TR\n", (double)0 /*lm_*/ , ph_ /* - tm_*/); fprintf(output, "1 -1 SC\n"); line_style(0); fprintf(output, "GS\n"); @@ -703,7 +722,7 @@ void Fl_PostScript_Graphics_Driver::rect(int x, int y, int w, int h) { } void Fl_PostScript_Graphics_Driver::rectf(int x, int y, int w, int h) { - fprintf(output, "%g %g %i %i FR\n", x-0.5, y-0.5, w, h); + clocale_printf( "%g %g %i %i FR\n", x-0.5, y-0.5, w, h); } void Fl_PostScript_Graphics_Driver::line(int x1, int y1, int x2, int y2) { @@ -895,8 +914,8 @@ void Fl_PostScript_Graphics_Driver::line_style(int style, int width, char* dashe if(style & 0x200){ // round and square caps, dash length need to be adjusted const double *dt = dashes_cap[style & 0xff]; while (*dt >= 0){ - fprintf(output, "%g ",width * (*dt)); - dt++; + clocale_printf("%g ",width * (*dt)); + dt++; } }else{ @@ -955,7 +974,7 @@ void Fl_PostScript_Graphics_Driver::font(int f, int s) { } #endif // USE_XFT #endif // USE_X11 - fprintf(output,"%.1f FS\n", ps_size); + clocale_printf("%.1f FS\n", ps_size); } } @@ -990,13 +1009,13 @@ void Fl_PostScript_Graphics_Driver::color(unsigned char r, unsigned char g, unsi cr_ = r; cg_ = g; cb_ = b; if (r == g && g == b) { double gray = r/255.0; - fprintf(output, "%g GL\n", gray); + clocale_printf("%g GL\n", gray); } else { double fr, fg, fb; fr = r/255.0; fg = g/255.0; fb = b/255.0; - fprintf(output, "%g %g %g SRGB\n", fr , fg , fb); + clocale_printf("%g %g %g SRGB\n", fr , fg , fb); } } @@ -1040,7 +1059,7 @@ static uchar *calc_mask(uchar *img, int w, int h, Fl_Color bg) // write to PostScript a bitmap image of a UTF8 string static void transformed_draw_extra(const char* str, int n, double x, double y, int w, - FILE *output, Fl_Graphics_Driver *driver, bool rtl) { + FILE *output, Fl_PostScript_Graphics_Driver *driver, bool rtl) { // scale for bitmask computation #if defined(USE_X11) && !USE_XFT float scale = 1; // don't scale because we can't expect to have scalable fonts @@ -1048,11 +1067,11 @@ static void transformed_draw_extra(const char* str, int n, double x, double y, i float scale = 2; #endif Fl_Fontsize old_size = driver->size(); - Fl_Font fontnum = driver->font(); + Fl_Font fontnum = driver->Fl_Graphics_Driver::font(); int w_scaled = (int)(w * (scale + 0.5)); int h = (int)(driver->height() * scale); // create an offscreen image of the string - Fl_Color text_color = driver->color(); + Fl_Color text_color = driver->Fl_Graphics_Driver::color(); Fl_Color bg_color = fl_contrast(FL_WHITE, text_color); Fl_Offscreen off = fl_create_offscreen(w_scaled, (int)(h+3*scale) ); fl_begin_offscreen(off); @@ -1080,7 +1099,7 @@ static void transformed_draw_extra(const char* str, int n, double x, double y, i delete[] img; // write the string image to PostScript as a scaled bitmask scale = w2 / float(w); - fprintf(output, "%g %g %g %g %d %d MI\n", x, y - h*0.77/scale, w2/scale, h/scale, w2, h); + driver->clocale_printf("%g %g %g %g %d %d MI\n", x, y - h*0.77/scale, w2/scale, h/scale, w2, h); uchar *di; int wmask = (w2+7)/8; for (int j = h - 1; j >= 0; j--){ @@ -1156,7 +1175,7 @@ void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, dou } fprintf(output, "%4.4X", utf); } - fprintf(output, "> %g %g show_pos_width\n", x, y); + clocale_printf("> %g %g show_pos_width\n", x, y); } void Fl_PostScript_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) { @@ -1165,11 +1184,11 @@ void Fl_PostScript_Graphics_Driver::rtl_draw(const char* str, int n, int x, int } void Fl_PostScript_Graphics_Driver::concat(){ - fprintf(output,"[%g %g %g %g %g %g] CT\n", fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y); + clocale_printf("[%g %g %g %g %g %g] CT\n", fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y); } void Fl_PostScript_Graphics_Driver::reconcat(){ - fprintf(output, "[%g %g %g %g %g %g] RCT\n" , fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y); + clocale_printf("[%g %g %g %g %g %g] RCT\n" , fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y); } ///////////////// transformed (double) drawings //////////////////////////////// @@ -1210,26 +1229,26 @@ void Fl_PostScript_Graphics_Driver::begin_polygon(){ void Fl_PostScript_Graphics_Driver::vertex(double x, double y){ if(shape_==POINTS){ - fprintf(output,"%g %g MT\n", x , y); + clocale_printf("%g %g MT\n", x , y); gap_=1; return; } if(gap_){ - fprintf(output,"%g %g MT\n", x , y); + clocale_printf("%g %g MT\n", x , y); gap_=0; }else - fprintf(output, "%g %g LT\n", x , y); + clocale_printf("%g %g LT\n", x , y); } void Fl_PostScript_Graphics_Driver::curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3){ if(shape_==NONE) return; if(gap_) - fprintf(output,"%g %g MT\n", x , y); + clocale_printf("%g %g MT\n", x , y); else - fprintf(output, "%g %g LT\n", x , y); + clocale_printf("%g %g LT\n", x , y); gap_=0; - fprintf(output, "%g %g %g %g %g %g curveto \n", x1 , y1 , x2 , y2 , x3 , y3); + clocale_printf("%g %g %g %g %g %g curveto \n", x1 , y1 , x2 , y2 , x3 , y3); } @@ -1238,13 +1257,13 @@ void Fl_PostScript_Graphics_Driver::circle(double x, double y, double r){ fprintf(output, "GS\n"); concat(); // fprintf(output, "BP\n"); - fprintf(output,"%g %g %g 0 360 arc\n", x , y , r); + clocale_printf("%g %g %g 0 360 arc\n", x , y , r); reconcat(); // fprintf(output, "ELP\n"); fprintf(output, "GR\n"); }else - fprintf(output, "%g %g %g 0 360 arc\n", x , y , r); + clocale_printf("%g %g %g 0 360 arc\n", x , y , r); } @@ -1252,9 +1271,9 @@ void Fl_PostScript_Graphics_Driver::arc(double x, double y, double r, double sta if(shape_==NONE) return; gap_=0; if(start>a) - fprintf(output, "%g %g %g %g %g arc\n", x , y , r , -start, -a); + clocale_printf("%g %g %g %g %g arc\n", x , y , r , -start, -a); else - fprintf(output, "%g %g %g %g %g arcn\n", x , y , r , -start, -a); + clocale_printf("%g %g %g %g %g arcn\n", x , y , r , -start, -a); } @@ -1263,12 +1282,12 @@ void Fl_PostScript_Graphics_Driver::arc(int x, int y, int w, int h, double a1, d fprintf(output, "GS\n"); //fprintf(output, "BP\n"); begin_line(); - fprintf(output, "%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); - fprintf(output, "%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); + clocale_printf("%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); + clocale_printf("%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); arc(0,0,1,a2,a1); // fprintf(output, "0 0 1 %g %g arc\n" , -a1 , -a2); - fprintf(output, "%g %g SC\n", 2.0/(w-1) , 2.0/(h-1) ); - fprintf(output, "%g %g TR\n", -x - w/2.0 +0.5 , -y - h/2.0 +0.5); + clocale_printf("%g %g SC\n", 2.0/(w-1) , 2.0/(h-1) ); + clocale_printf("%g %g TR\n", -x - w/2.0 +0.5 , -y - h/2.0 +0.5); end_line(); // fprintf(output, "%g setlinewidth\n", 2/sqrt(w*h)); @@ -1281,8 +1300,8 @@ void Fl_PostScript_Graphics_Driver::arc(int x, int y, int w, int h, double a1, d void Fl_PostScript_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) { fprintf(output, "GS\n"); begin_polygon(); - fprintf(output, "%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); - fprintf(output, "%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); + clocale_printf("%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); + clocale_printf("%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); vertex(0,0); arc(0.0,0.0, 1, a2, a1); end_polygon(); @@ -1324,10 +1343,10 @@ void Fl_PostScript_Graphics_Driver::end_polygon(){ void Fl_PostScript_Graphics_Driver::transformed_vertex(double x, double y){ reconcat(); if(gap_){ - fprintf(output, "%g %g MT\n", x , y); + clocale_printf("%g %g MT\n", x , y); gap_=0; }else - fprintf(output, "%g %g LT\n", x , y); + clocale_printf("%g %g LT\n", x , y); concat(); } @@ -1341,7 +1360,7 @@ void Fl_PostScript_Graphics_Driver::push_clip(int x, int y, int w, int h) { fprintf(output, "CR\nCS\n"); if(lang_level_<3) recover(); - fprintf(output, "%g %g %i %i CL\n", clip_->x-0.5 , clip_->y-0.5 , clip_->w , clip_->h); + clocale_printf("%g %g %i %i CL\n", clip_->x-0.5 , clip_->y-0.5 , clip_->w , clip_->h); } @@ -1362,7 +1381,7 @@ void Fl_PostScript_Graphics_Driver::pop_clip() { delete c; fprintf(output, "CR\nCS\n"); if(clip_ && clip_->w >0) - fprintf(output, "%g %g %i %i CL\n", clip_->x - 0.5, clip_->y - 0.5, clip_->w , clip_->h); + clocale_printf("%g %g %i %i CL\n", clip_->x - 0.5, clip_->y - 0.5, clip_->w , clip_->h); // uh, -0.5 is to match screen clipping, for floats there should be something beter if(lang_level_<3) recover(); @@ -1413,7 +1432,6 @@ int Fl_PostScript_Graphics_Driver::not_clipped(int x, int y, int w, int h){ return 0; } - void Fl_PostScript_File_Device::margins(int *left, int *top, int *right, int *bottom) // to implement { Fl_PostScript_Graphics_Driver *ps = driver(); @@ -1442,7 +1460,7 @@ void Fl_PostScript_File_Device::origin(int x, int y) x_offset = x; y_offset = y; Fl_PostScript_Graphics_Driver *ps = driver(); - fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", + ps->clocale_printf("GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, x, y, ps->angle); } @@ -1452,7 +1470,7 @@ void Fl_PostScript_File_Device::scale (float s_x, float s_y) Fl_PostScript_Graphics_Driver *ps = driver(); ps->scale_x = s_x; ps->scale_y = s_y; - fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %f rotate GS\n", + ps->clocale_printf("GR GR GS %d %d TR %f %f SC %f rotate GS\n", ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, ps->angle); } @@ -1460,7 +1478,7 @@ void Fl_PostScript_File_Device::rotate (float rot_angle) { Fl_PostScript_Graphics_Driver *ps = driver(); ps->angle = - rot_angle; - fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", + ps->clocale_printf("GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, x_offset, y_offset, ps->angle); } -- cgit v1.2.3