Geant4 Cross Reference |
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; 67 m_buffer[METAFILE_RECORD_LENGTH()]= '\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 140 PS_SCALE(1/METAFILE_SCALE(),1/METAFILE_SCALE()); 141 PS_TRANSLATE(m_deviceWidth/20,m_deviceHeight/30); 142 143 float scale; 144 if(m_deviceWidth<=m_deviceHeight) { 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 { 155 PS_TRANSLATE(m_deviceWidth,0); 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 179 void PS_BEGIN_PAGE(){ 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; 426 float m_deviceWidth; 427 float m_deviceHeight; 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 */