g4tools  5.4.0
wps
Go to the documentation of this file.
1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
2 // See the file tools.license for terms.
3 
4 #ifndef tools_wps
5 #define tools_wps
6 
7 #include <ctime>
8 
9 #include <string>
10 #include <ostream>
11 #include <cstring>
12 #include "sprintf"
13 
14 namespace tools {
15 
16 class wps {
17  typedef unsigned char Uchar;
18  typedef unsigned int Uint;
19 
20 public:
21  typedef float VCol;
22  typedef bool(*rgb_func)(void*,unsigned int,unsigned int,VCol&,VCol&,VCol&);
23 public:
24  wps(std::ostream& a_out):m_out(a_out){
25  m_deviceWidth = (8.5f-1.f)*72*METAFILE_SCALE(); // 540 * METAFILE_SCALE
26  m_deviceHeight = 11*72*METAFILE_SCALE(); // 792 * METAFILE_SCALE
27  m_pageNumber = 0;
28  //m_pagePos = 0;
29  //m_markSize = 2;
30  m_file = 0;
31  m_fname.clear();
32  m_string.clear();
33  m_gsave = 0;
34  m_buffer = new Uchar[METAFILE_RECORD_LENGTH()+1];
35  m_number = 0;
36 
37  //m_param.shade = shade_color;
38  }
39 
40  virtual ~wps(){
41  if(m_file) close_file();
42  m_string.clear();
43  if(m_gsave) {
44  m_out << "tools::wps::~wps :"
45  << " bad gsave/grestore balance : " << m_gsave
46  << std::endl;
47  }
48  m_gsave = 0;
49  delete [] m_buffer;
50  }
51 //protected:
52 private:
53  wps(const wps& a_from):m_out(a_from.m_out){}
54  wps& operator=(const wps&){return *this;}
55 public:
56  //const std::string& file_name() const {return m_fname;}
57  //FILE* get_FILE() const {return m_file;}
58 
59  bool open_file(const std::string& a_name,bool a_anonymous = false){
60  if(m_file) return false;
61 
62  m_file = ::fopen(a_name.c_str(),"wb");
63  if(!m_file) return false;
64  m_fname = a_name;
65 
66  m_number = 0;
68  m_pageNumber = 0;
69  // Header :
70  PrintFLN("%%!PS-Adobe-2.0");
71  if(a_anonymous) { //usefull for integration tests.
72  } else {
73  PrintFLN("%%%%Creator: tools::wps.");
74  PrintFLN("%%%%CreationDate: %s",get_date());
75  PrintFLN("%%%%Title: %s",m_fname.c_str());
76  }
77  PrintFLN("%%%%Pages: (atend)");
78  PrintFLN("%%%%BoundingBox: 0 0 %d %d",(int)m_deviceWidth,(int)m_deviceHeight);
79  PrintFLN("%%%%DocumentFonts: Courier-Bold");
80  PrintFLN("%%%%DocumentPaperSizes: a4");
81  PrintFLN("%%%%EndComments");
82  // postscript :
83  PS_SAVE();
84 /*
85  // General :
86  in_buffer("/n {newpath} def ");
87  in_buffer("/cl {closepath} def ");
88  in_buffer("/s {stroke} def ");
89  in_buffer("/f {fill} def ");
90  // Move :
91  in_buffer("/m {moveto} def ");
92  in_buffer("/rm {rmoveto} def ");
93  in_buffer("/rl {rlineto} def ");
94  // Line :
95  in_buffer("/lc {setlinecap} def ");
96  in_buffer("/lw {setlinewidth} def ");
97  in_buffer("/rgb {setrgbcolor} def ");
98  in_buffer("/ss {[] 0 setdash} def "); // style solid.
99  in_buffer("/sd {[12 6] 0 setdash} def "); // style dashed
100  in_buffer("/so {[6 12] 0 setdash} def "); // style dotted
101  in_buffer("/sdo {[18 12 6 12] 0 setdash} def "); // dash dotted
102  // Mark :
103  m_markSize = 2.;
104  in_buffer("/ms 2. def /msi .5 def "); // mark size
105  in_buffer("/cross {ms ms scale -1. -1. rm ");
106  in_buffer ("2. 2. rl 0. -2. rm -2. 2. rl msi msi scale} def ");
107  in_buffer("/plus {ms ms scale -1. 0. rm 2. 0. rl ");
108  in_buffer("-1. 1. rm 0. -2. rl msi msi scale} def ");
109  in_buffer("/asterisk {ms ms scale -1. 0. rm 2. 0. rl -1. 1. rm ");
110  in_buffer("0. -2. rl 0. 1. rm -0.707 -0.707 rm 1.414 1.414 rl ");
111  in_buffer("0. -1.414 rm -1.414 1.414 rl msi msi scale} def ");
112  in_buffer("/star {ms ms scale 0. 1. rm -0.6 -1.5 rl ");
113  in_buffer("1.2 0. rl -0.6 1.5 rl msi msi scale} def ");
114  // Text :
115  in_buffer("/sh {show} def ");
116  in_buffer("/df {/Courier-Bold findfont} def ");
117  in_buffer("/mf {makefont setfont} def ");
118 */
119 
120  PrintFLN("%%%%EndProlog");
121 
122  return true;
123  }
124 
125  bool close_file(){
126  if(!m_file) return false;
127  PS_RESTORE();
128  PrintFLN("%%%%Trailer");
129  PrintFLN("%%%%Pages: %d",m_pageNumber);
130  PrintFLN("%%%%EOF");
131  ::fclose(m_file);
132  m_file = 0;
133  m_fname.clear();
134  return true;
135  }
136 
137  void PS_PAGE_SCALE(float a_width,float a_height,bool a_portrait = true){
138  //NOTE : no check done on [a_width,a_height]<=0
139 
142 
143  float scale;
145  scale = (a_height<=a_width?m_deviceWidth/a_width:m_deviceWidth/a_height);
146  } else {
147  scale = (a_height<=a_width?m_deviceHeight/a_width:m_deviceHeight/a_height);
148  }
149 
150  {float xtra,ytra;
151  if(a_portrait) {
152  xtra = (m_deviceWidth - scale * a_width)/2;
153  ytra = (m_deviceHeight - scale * a_height)/2;
154  } else {
156  PS_ROTATE(90);
157  xtra = (m_deviceHeight - scale * a_width)/2;
158  ytra = (m_deviceWidth - scale * a_height)/2;
159  }
160  PS_TRANSLATE(xtra,ytra);}
161 
162  PS_SCALE(scale,scale);
163  }
164 
165  void PS_SCALE(float a_x,float a_y) {
166  in_buffer("%.2f %.2f scale ",a_x,a_y);
167  }
168 
169  void PS_TRANSLATE(float a_x,float a_y){
170  in_buffer("%.2f %.2f translate ",a_x,a_y);
171  }
172 
173  void PS_ROTATE(float a_x){in_buffer("%.2f rotate ",a_x);}
174 
175  void PS_SAVE(){in_buffer("gsave ");m_gsave++;}
176 
177  void PS_RESTORE(){in_buffer("grestore ");m_gsave--;}
178 
180  m_pageNumber++;
181  PrintFLN("%%%%Page: %d %d",m_pageNumber,m_pageNumber);
182  PS_SAVE();
183  }
184 
185  void PS_END_PAGE(){
186  in_buffer("showpage ");
187  PS_RESTORE();
188  }
189 
190  enum rgb_nbit {
191  rgb_bw = 0,
192  rgb_2 = 2,
193  rgb_4 = 4,
194  rgb_8 = 8
195  };
196 
197  void PS_IMAGE(Uint a_width,Uint a_height,rgb_nbit a_nbit,rgb_func a_proc,void* a_tag){
198  //NOTE : no check done on [a_width,a_height] being zero.
199 
200  Uint row,col;
201  VCol dr,dg,db;
202  Uchar red,green,blue,b;
203 
204  PS_SAVE();
205  in_buffer("%d %d scale ", a_width, a_height );
206  bool status = true;
207  if(a_nbit==rgb_bw) { //grey or black_white
208  in_buffer ("/picstr %d string def ",a_width);
209  in_buffer ("%d %d %d ",a_width,a_height,8);
210  in_buffer ("[ %d 0 0 -%d 0 %d ] ",a_width,a_height,a_height);
211  in_buffer ("{ currentfile picstr readhexstring pop } " );
212  PrintFLN ("image " );
213  for ( row = 0; row < a_height; row++ ) {
214  for ( col = 0; col < a_width; col++) {
215  status = a_proc(a_tag,col,row,dr,dg,db)?status:false;
216  VCol fgrey = rgb2grey(dr,dg,db);
217  Uchar grey = (Uchar) ( 255.0F * fgrey);
218  WriteByte(grey);
219  }
220  }
221  int nbhex = a_width * a_height * 2;
222  PrintFLN ("%%%% nbhex digit :%d ",nbhex);
223  PrintFLN ("%%%% nbhex/record_length :%d ",
224  int(nbhex/METAFILE_RECORD_LENGTH()));
225  PrintFLN ("%%%% nbhex%%record_length :%d ",
226  int(nbhex%METAFILE_RECORD_LENGTH()));
227 
228  } else if(a_nbit==rgb_2) {
229  int nbyte2 = (a_width * 3)/4;
230  nbyte2 /=3;
231  nbyte2 *=3;
232  Uint col_max = (nbyte2 * 4)/3;
233  // 2 bit for r and g and b.
234  // rgbs following each other.
235  in_buffer ("/rgbstr %d string def ",nbyte2);
236  in_buffer ("%d %d %d ",col_max,a_height,2);
237  in_buffer ("[ %d 0 0 -%d 0 %d ] ",col_max,a_height,a_height);
238  in_buffer ("{ currentfile rgbstr readhexstring pop } " );
239  in_buffer ("false 3 " );
240  PrintFLN ("colorimage " );
241  for ( row = 0; row < a_height; row++ ) {
242  for ( col = 0; col < col_max; col+=4) {
243  status = a_proc(a_tag,col,row,dr,dg,db)?status:false;
244  red = (Uchar) ( 3.0F * dr);
245  green = (Uchar) ( 3.0F * dg);
246  blue = (Uchar) ( 3.0F * db);
247  b = red;
248  b = (b<<2)+green;
249  b = (b<<2)+blue;
250 
251  status = a_proc(a_tag,col+1,row,dr,dg,db)?status:false;
252  red = (Uchar) ( 3.0F * dr);
253  green = (Uchar) ( 3.0F * dg);
254  blue = (Uchar) ( 3.0F * db);
255  b = (b<<2)+red;
256  WriteByte(b);
257 
258  b = green;
259  b = (b<<2)+blue;
260 
261  status = a_proc(a_tag,col+2,row,dr,dg,db)?status:false;
262  red = (Uchar) ( 3.0F * dr);
263  green = (Uchar) ( 3.0F * dg);
264  blue = (Uchar) ( 3.0F * db);
265  b = (b<<2)+red;
266  b = (b<<2)+green;
267  WriteByte(b);
268  b = blue;
269 
270  status = a_proc(a_tag,col+3,row,dr,dg,db)?status:false;
271  red = (Uchar) ( 3.0F * dr);
272  green = (Uchar) ( 3.0F * dg);
273  blue = (Uchar) ( 3.0F * db);
274  b = (b<<2)+red;
275  b = (b<<2)+green;
276  b = (b<<2)+blue;
277  WriteByte(b);
278  }
279  }
280 
281  } else if(a_nbit==rgb_4) {
282  int nbyte4 = (a_width * 3)/2;
283  nbyte4 /=3;
284  nbyte4 *=3;
285  Uint col_max = (nbyte4 * 2)/3;
286  // 4 bit for r and g and b.
287  // rgbs following each other.
288  in_buffer ("/rgbstr %d string def ",nbyte4);
289  in_buffer ("%d %d %d ",col_max,a_height,4);
290  in_buffer ("[ %d 0 0 -%d 0 %d ] ",col_max,a_height,a_height);
291  in_buffer ("{ currentfile rgbstr readhexstring pop } " );
292  in_buffer ("false 3 " );
293  PrintFLN ("colorimage " );
294  for ( row = 0; row < a_height; row++ ) {
295  for ( col = 0; col < col_max; col+=2) {
296  status = a_proc(a_tag,col,row,dr,dg,db)?status:false;
297  red = (Uchar) ( 15.0F * dr);
298  green = (Uchar) ( 15.0F * dg);
299  in_buffer ("%x%x",red,green);
300  blue = (Uchar) ( 15.0F * db);
301 
302  status = a_proc(a_tag,col+1,row,dr,dg,db)?status:false;
303  red = (Uchar) ( 15.0F * dr);
304  in_buffer ("%x%x",blue,red);
305  green = (Uchar) ( 15.0F * dg);
306  blue = (Uchar) ( 15.0F * db);
307  in_buffer ("%x%x",green,blue);
308  }
309  }
310 
311  } else if(a_nbit==rgb_8) {
312  int nbyte8 = a_width * 3;
313  // 8 bit for r and g and b.
314  in_buffer ("/rgbstr %d string def ",nbyte8);
315  in_buffer ("%d %d %d ",a_width,a_height,8);
316  in_buffer ("[ %d 0 0 -%d 0 %d ] ",a_width,a_height,a_height);
317  in_buffer ("{ currentfile rgbstr readhexstring pop } " );
318  in_buffer ("false 3 " );
319  PrintFLN ("colorimage " );
320  for ( row = 0; row < a_height; row++ ) {
321  for ( col = 0; col < a_width; col++) {
322  status = a_proc(a_tag,col,row,dr,dg,db)?status:false;
323  red = (Uchar) ( 255.0F * dr);
324  WriteByte (red);
325  green = (Uchar) ( 255.0F * dg);
326  WriteByte (green);
327  blue = (Uchar) ( 255.0F * db);
328  WriteByte (blue);
329  }
330  }
331  } else {
332  m_out << "PS_IMAGE :"
333  << " unknown rgb nbit " << a_nbit
334  << std::endl;
335  }
336  if(!status) {
337  m_out << "PS_IMAGE :"
338  << " problem to retrieve some pixel rgb."
339  << std::endl;
340  }
341  PS_RESTORE();
342  }
343 
344 protected:
345  static size_t METAFILE_RECORD_LENGTH() {return 80;}
346 
347  static float METAFILE_SCALE() {return 1.0f;}
348 
349  static char* get_date(){
350  char* string;
351  time_t d;
352  ::time(&d);
353  string = ::ctime(&d);
354  string[24] = '\0';
355  return string;
356  }
357 
358  static VCol rgb2grey(VCol a_red,VCol a_green,VCol a_blue){
359  return (0.30f * a_red + 0.59f * a_green + 0.11f * a_blue);
360  }
361 
362  bool in_buffer(const char* a_format,...){
363  va_list args;
364  va_start(args,a_format);
365  bool status = vsprintf(m_string,2048,a_format,args);
366  va_end(args);
367  if(!status) {
368  m_out << "tools::wps::in_buffer : overflow." << std::endl;
369  return false;
370  }
371 
372  size_t length = m_string.size();
373  if(length>METAFILE_RECORD_LENGTH()) {
374  m_out << "tools::wps::in_buffer : overflow." << std::endl;
375  return false;
376  }
377 
378  size_t nlength = m_number + length;
379  if(nlength>METAFILE_RECORD_LENGTH()) {
380  m_buffer[m_number] = '\0';
381  if(::fprintf(m_file,"%s\n",(char*)m_buffer)<0) {
382  m_out << "tools::wps::in_buffer : fprintf failed." << std::endl;
383  }
384  m_number = 0;
385  nlength = length;
386  }
387  Uchar* pointer = m_buffer + m_number;
388  ::strcpy((char*)pointer,m_string.c_str());
389  m_number = nlength;
390  return true;
391  }
392 
393  bool PrintFLN(const char* a_format,...){
394  va_list args;
395  va_start(args,a_format);
396  bool status = vsprintf(m_string,2048,a_format,args);
397  va_end(args);
398  if(!status) {
399  m_out << "tools::wps::PrintFLN : overflow." << std::endl;
400  return false;
401  }
402 
403  // put buffer in file :
404  if(m_number>0) {
405  m_buffer[m_number] = '\0';
406  if(::fprintf(m_file,"%s\n",(char*)m_buffer)<0) {
407  m_out << "tools::wps::PrintFLN : fprintf failed." << std::endl;
408  }
409  m_number = 0;
410  }
411  if(::fprintf(m_file,"%s\n",m_string.c_str())<0) {
412  m_out << "tools::wps::PrintFLN : fprintf failed." << std::endl;
413  }
414 
415  return true;
416  }
417 
418  void WriteByte(Uchar a_byte){
419  Uchar h = a_byte / 16;
420  Uchar l = a_byte % 16;
421  in_buffer("%x%x",h,l);
422  }
423 
424 protected:
425  std::ostream& m_out;
428  unsigned int m_pageNumber;
429 //double m_markSize;
430  FILE* m_file;
431  std::string m_fname;
432  std::string m_string;
433  int m_gsave;
434  Uchar* m_buffer;
435  size_t m_number;
436 //struct {
437 // int shade;
438 // int nbit;
439 //} m_param;
440 };
441 
442 }
443 
444 #endif
445 
446 /*
447  enum {
448  shade_color = 0,
449  shade_grey = 1,
450  shade_black_white = 2
451  };
452 
453  void PS_BACKGROUND(double a_r,double a_g,double a_b,
454  double a_width,double a_height,
455  bool a_do_back = true){
456  PS_NEWPATH();
457  PS_MOVE (0.,0.);
458  PS_RLINETO (a_width,0.);
459  PS_RLINETO (0.,a_height);
460  PS_RLINETO (-a_width,0.);
461  PS_RLINETO (0.,-a_height);
462  PS_CLOSEPATH();
463  if(a_do_back) {
464  PS_SAVE();
465  PS_RGB(a_r,a_g,a_b);
466  PS_FILL();
467  PS_RESTORE();
468  }
469  in_buffer("clip ");
470  }
471 
472  void PS_RGB(double a_r,double a_g,double a_b){
473  if(m_param.shade==shade_color)
474  in_buffer("%.2f %.2f %.2f rgb ",a_r,a_g,a_b);
475  else if(m_param.shade==shade_grey)
476  in_buffer("%.2f setgray ",rgb2grey(a_r,a_g,a_b));
477  else if(m_param.shade==shade_black_white)
478  in_buffer("0. setgray ",rgb2grey(a_r,a_g,a_b));
479  }
480 
481  void PS_LINE_WIDTH(int a_width){in_buffer("%.1f lw ",float(a_width));}
482 
483  void PS_NEWPATH() {in_buffer("n ");}
484  void PS_STROKE() {in_buffer("s ");}
485  void PS_FILL() {in_buffer("f ");}
486  void PS_CLOSEPATH() {in_buffer("cl ");}
487  void PS_CAP(double a_x) {in_buffer ("%1d lc ",a_x);}
488  void PS_RLINETO(double a_x,double a_y) {
489  in_buffer ("%.2f %.2f rl ",a_x,a_y);
490  }
491  void PS_MOVE(double a_x,double a_y) {
492  in_buffer ("%.2f %.2f m ",a_x,a_y);
493  }
494 
495  void PS_FRAME(double a_r,double a_g,double a_b,
496  double a_width,double a_height){
497  PS_NEWPATH ();
498  PS_MOVE (0.,0.);
499  PS_RLINETO (a_width,0.);
500  PS_RLINETO (0.,a_height);
501  PS_RLINETO (-a_width,0.);
502  PS_RLINETO (0.,-a_height);
503  PS_CLOSEPATH ();
504  PS_RGB (a_r,a_g,a_b);
505  PS_LINE_WIDTH(1);
506  PS_CAP (1);
507  in_buffer ("ss ");
508  PS_STROKE();
509  }
510 */
tools::wps::m_out
std::ostream & m_out
Definition: wps:425
tools::wps::rgb_8
@ rgb_8
Definition: wps:194
tools::wps::m_gsave
int m_gsave
Definition: wps:433
tools::wps::m_fname
std::string m_fname
Definition: wps:431
tools::wps::close_file
bool close_file()
Definition: wps:125
tools::vsprintf
bool vsprintf(std::string &a_string, int a_length, const char *a_format, va_list a_args)
Definition: sprintf:12
tools::wps::rgb2grey
static VCol rgb2grey(VCol a_red, VCol a_green, VCol a_blue)
Definition: wps:358
tools::wps::m_deviceWidth
float m_deviceWidth
Definition: wps:426
tools::wps::m_file
FILE * m_file
Definition: wps:430
tools::wps::m_number
size_t m_number
Definition: wps:435
tools::wps::PS_PAGE_SCALE
void PS_PAGE_SCALE(float a_width, float a_height, bool a_portrait=true)
Definition: wps:137
tools::wps::PS_END_PAGE
void PS_END_PAGE()
Definition: wps:185
tools::wps::m_pageNumber
unsigned int m_pageNumber
Definition: wps:428
tools::wps::m_deviceHeight
float m_deviceHeight
Definition: wps:427
tools::wps::rgb_func
bool(* rgb_func)(void *, unsigned int, unsigned int, VCol &, VCol &, VCol &)
Definition: wps:22
tools::wps::VCol
float VCol
Definition: wps:21
tools::wps::open_file
bool open_file(const std::string &a_name, bool a_anonymous=false)
Definition: wps:59
tools::args
Definition: args:24
sprintf
tools::wps::PS_BEGIN_PAGE
void PS_BEGIN_PAGE()
Definition: wps:179
tools::wps::m_buffer
Uchar * m_buffer
Definition: wps:434
tools::wps
Definition: wps:16
tools::wps::PS_ROTATE
void PS_ROTATE(float a_x)
Definition: wps:173
tools::wps::rgb_4
@ rgb_4
Definition: wps:193
tools::wps::PS_SCALE
void PS_SCALE(float a_x, float a_y)
Definition: wps:165
tools::wps::~wps
virtual ~wps()
Definition: wps:40
tools::wps::METAFILE_RECORD_LENGTH
static size_t METAFILE_RECORD_LENGTH()
Definition: wps:345
tools::wps::WriteByte
void WriteByte(Uchar a_byte)
Definition: wps:418
tools::wps::rgb_bw
@ rgb_bw
Definition: wps:191
tools::wps::PS_IMAGE
void PS_IMAGE(Uint a_width, Uint a_height, rgb_nbit a_nbit, rgb_func a_proc, void *a_tag)
Definition: wps:197
tools
inlined C code : ///////////////////////////////////
Definition: aida_ntuple:26
tools::wps::METAFILE_SCALE
static float METAFILE_SCALE()
Definition: wps:347
tools::wps::PS_RESTORE
void PS_RESTORE()
Definition: wps:177
tools::wps::get_date
static char * get_date()
Definition: wps:349
tools::wps::m_string
std::string m_string
Definition: wps:432
tools::wps::wps
wps(std::ostream &a_out)
Definition: wps:24
tools::wps::rgb_2
@ rgb_2
Definition: wps:192
tools::wps::PS_TRANSLATE
void PS_TRANSLATE(float a_x, float a_y)
Definition: wps:169
tools::wps::PrintFLN
bool PrintFLN(const char *a_format,...)
Definition: wps:393
tools::wps::in_buffer
bool in_buffer(const char *a_format,...)
Definition: wps:362
tools::wps::PS_SAVE
void PS_SAVE()
Definition: wps:175
tools::wps::rgb_nbit
rgb_nbit
Definition: wps:190