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
This commit is contained in:
parent
3ce67eb594
commit
c7f0ee3bd0
@ -25,6 +25,7 @@
|
||||
|
||||
#include <FL/Fl_Paged_Device.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
\brief PostScript graphical backend.
|
||||
@ -59,7 +60,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
class FL_EXPORT Fl_PostScript_Graphics_Driver : public Fl_Graphics_Driver {
|
||||
public:
|
||||
public:
|
||||
static const char *class_id;
|
||||
const char *class_name() {return class_id;};
|
||||
Fl_PostScript_Graphics_Driver();
|
||||
@ -205,6 +206,7 @@ class Clip {
|
||||
void draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void draw(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
int clocale_printf(const char *format, ...);
|
||||
~Fl_PostScript_Graphics_Driver();
|
||||
};
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include <stdio.h>
|
||||
#include <FL/Fl_PostScript.H>
|
||||
#include <FL/Fl_Native_File_Chooser.H>
|
||||
#include <stdarg.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user