Warning, /include/Geant4/tools/wps is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_wps
0005 #define tools_wps
0006
0007 #include <ctime>
0008
0009 #include <string>
0010 #include <ostream>
0011 #include <cstring>
0012 #include "sprintf"
0013
0014 namespace tools {
0015
0016 class wps {
0017 typedef unsigned char Uchar;
0018 typedef unsigned int Uint;
0019
0020 public:
0021 typedef float VCol;
0022 typedef bool(*rgb_func)(void*,unsigned int,unsigned int,VCol&,VCol&,VCol&);
0023 public:
0024 wps(std::ostream& a_out):m_out(a_out){
0025 m_deviceWidth = (8.5f-1.f)*72*METAFILE_SCALE(); // 540 * METAFILE_SCALE
0026 m_deviceHeight = 11*72*METAFILE_SCALE(); // 792 * METAFILE_SCALE
0027 m_pageNumber = 0;
0028 m_file = 0;
0029 m_fname.clear();
0030 m_string.clear();
0031 m_gsave = 0;
0032 m_buffer = new Uchar[METAFILE_RECORD_LENGTH()+1];
0033 m_number = 0;
0034 }
0035
0036 virtual ~wps(){
0037 if(m_file) close_file();
0038 m_string.clear();
0039 if(m_gsave) {
0040 m_out << "tools::wps::~wps :"
0041 << " bad gsave/grestore balance : " << m_gsave
0042 << std::endl;
0043 }
0044 m_gsave = 0;
0045 delete [] m_buffer;
0046 }
0047 private:
0048 wps(const wps& a_from):m_out(a_from.m_out){}
0049 wps& operator=(const wps&){return *this;}
0050 public:
0051 bool open_file(const std::string& a_name,bool a_anonymous = false){
0052 if(m_file) return false;
0053
0054 m_file = ::fopen(a_name.c_str(),"wb");
0055 if(!m_file) return false;
0056 m_fname = a_name;
0057
0058 m_number = 0;
0059 m_buffer[METAFILE_RECORD_LENGTH()]= '\0';
0060 m_pageNumber = 0;
0061 // Header :
0062 PrintFLN("%%!PS-Adobe-2.0");
0063 if(a_anonymous) { //usefull for integration tests.
0064 } else {
0065 PrintFLN("%%%%Creator: tools::wps.");
0066 PrintFLN("%%%%CreationDate: %s",get_date());
0067 PrintFLN("%%%%Title: %s",m_fname.c_str());
0068 }
0069 PrintFLN("%%%%Pages: (atend)");
0070 PrintFLN("%%%%BoundingBox: 0 0 %d %d",(int)m_deviceWidth,(int)m_deviceHeight);
0071 PrintFLN("%%%%DocumentFonts: Courier-Bold");
0072 PrintFLN("%%%%DocumentPaperSizes: a4");
0073 PrintFLN("%%%%EndComments");
0074 // postscript :
0075 PS_SAVE();
0076 PrintFLN("%%%%EndProlog");
0077
0078 return true;
0079 }
0080
0081 bool close_file(){
0082 if(!m_file) return false;
0083 PS_RESTORE();
0084 PrintFLN("%%%%Trailer");
0085 PrintFLN("%%%%Pages: %d",m_pageNumber);
0086 PrintFLN("%%%%EOF");
0087 ::fclose(m_file);
0088 m_file = 0;
0089 m_fname.clear();
0090 return true;
0091 }
0092
0093 void PS_PAGE_SCALE(float a_width,float a_height,bool a_portrait = true){
0094 //NOTE : no check done on [a_width,a_height]<=0
0095
0096 PS_SCALE(1/METAFILE_SCALE(),1/METAFILE_SCALE());
0097 PS_TRANSLATE(m_deviceWidth/20,m_deviceHeight/30);
0098
0099 float scale;
0100 if(m_deviceWidth<=m_deviceHeight) {
0101 scale = (a_height<=a_width?m_deviceWidth/a_width:m_deviceWidth/a_height);
0102 } else {
0103 scale = (a_height<=a_width?m_deviceHeight/a_width:m_deviceHeight/a_height);
0104 }
0105
0106 {float xtra,ytra;
0107 if(a_portrait) {
0108 xtra = (m_deviceWidth - scale * a_width)/2;
0109 ytra = (m_deviceHeight - scale * a_height)/2;
0110 } else {
0111 PS_TRANSLATE(m_deviceWidth,0);
0112 PS_ROTATE(90);
0113 xtra = (m_deviceHeight - scale * a_width)/2;
0114 ytra = (m_deviceWidth - scale * a_height)/2;
0115 }
0116 PS_TRANSLATE(xtra,ytra);}
0117
0118 PS_SCALE(scale,scale);
0119 }
0120
0121 void PS_SCALE(float a_x,float a_y) {
0122 in_buffer("%.2f %.2f scale ",a_x,a_y);
0123 }
0124
0125 void PS_TRANSLATE(float a_x,float a_y){
0126 in_buffer("%.2f %.2f translate ",a_x,a_y);
0127 }
0128
0129 void PS_ROTATE(float a_x){in_buffer("%.2f rotate ",a_x);}
0130
0131 void PS_SAVE(){in_buffer("gsave ");m_gsave++;}
0132
0133 void PS_RESTORE(){in_buffer("grestore ");m_gsave--;}
0134
0135 void PS_BEGIN_PAGE(){
0136 m_pageNumber++;
0137 PrintFLN("%%%%Page: %d %d",m_pageNumber,m_pageNumber);
0138 PS_SAVE();
0139 }
0140
0141 void PS_END_PAGE(){
0142 in_buffer("showpage ");
0143 PS_RESTORE();
0144 }
0145
0146 enum rgb_nbit {
0147 rgb_bw = 0,
0148 rgb_2 = 2,
0149 rgb_4 = 4,
0150 rgb_8 = 8
0151 };
0152
0153 void PS_IMAGE(Uint a_width,Uint a_height,rgb_nbit a_nbit,rgb_func a_proc,void* a_tag){
0154 //NOTE : no check done on [a_width,a_height] being zero.
0155
0156 Uint row,col;
0157 VCol dr,dg,db;
0158 Uchar red,green,blue,b;
0159
0160 PS_SAVE();
0161 in_buffer("%d %d scale ", a_width, a_height );
0162 bool status = true;
0163 if(a_nbit==rgb_bw) { //grey or black_white
0164 in_buffer ("/picstr %d string def ",a_width);
0165 in_buffer ("%d %d %d ",a_width,a_height,8);
0166 in_buffer ("[ %d 0 0 -%d 0 %d ] ",a_width,a_height,a_height);
0167 in_buffer ("{ currentfile picstr readhexstring pop } " );
0168 PrintFLN ("image " );
0169 for ( row = 0; row < a_height; row++ ) {
0170 for ( col = 0; col < a_width; col++) {
0171 status = a_proc(a_tag,col,row,dr,dg,db)?status:false;
0172 VCol fgrey = rgb2grey(dr,dg,db);
0173 Uchar grey = (Uchar) ( 255.0F * fgrey);
0174 WriteByte(grey);
0175 }
0176 }
0177 int nbhex = a_width * a_height * 2;
0178 PrintFLN ("%%%% nbhex digit :%d ",nbhex);
0179 PrintFLN ("%%%% nbhex/record_length :%d ",
0180 int(nbhex/METAFILE_RECORD_LENGTH()));
0181 PrintFLN ("%%%% nbhex%%record_length :%d ",
0182 int(nbhex%METAFILE_RECORD_LENGTH()));
0183
0184 } else if(a_nbit==rgb_2) {
0185 int nbyte2 = (a_width * 3)/4;
0186 nbyte2 /=3;
0187 nbyte2 *=3;
0188 Uint col_max = (nbyte2 * 4)/3;
0189 // 2 bit for r and g and b.
0190 // rgbs following each other.
0191 in_buffer ("/rgbstr %d string def ",nbyte2);
0192 in_buffer ("%d %d %d ",col_max,a_height,2);
0193 in_buffer ("[ %d 0 0 -%d 0 %d ] ",col_max,a_height,a_height);
0194 in_buffer ("{ currentfile rgbstr readhexstring pop } " );
0195 in_buffer ("false 3 " );
0196 PrintFLN ("colorimage " );
0197 for ( row = 0; row < a_height; row++ ) {
0198 for ( col = 0; col < col_max; col+=4) {
0199 status = a_proc(a_tag,col,row,dr,dg,db)?status:false;
0200 red = (Uchar) ( 3.0F * dr);
0201 green = (Uchar) ( 3.0F * dg);
0202 blue = (Uchar) ( 3.0F * db);
0203 b = red;
0204 b = (b<<2)+green;
0205 b = (b<<2)+blue;
0206
0207 status = a_proc(a_tag,col+1,row,dr,dg,db)?status:false;
0208 red = (Uchar) ( 3.0F * dr);
0209 green = (Uchar) ( 3.0F * dg);
0210 blue = (Uchar) ( 3.0F * db);
0211 b = (b<<2)+red;
0212 WriteByte(b);
0213
0214 b = green;
0215 b = (b<<2)+blue;
0216
0217 status = a_proc(a_tag,col+2,row,dr,dg,db)?status:false;
0218 red = (Uchar) ( 3.0F * dr);
0219 green = (Uchar) ( 3.0F * dg);
0220 blue = (Uchar) ( 3.0F * db);
0221 b = (b<<2)+red;
0222 b = (b<<2)+green;
0223 WriteByte(b);
0224 b = blue;
0225
0226 status = a_proc(a_tag,col+3,row,dr,dg,db)?status:false;
0227 red = (Uchar) ( 3.0F * dr);
0228 green = (Uchar) ( 3.0F * dg);
0229 blue = (Uchar) ( 3.0F * db);
0230 b = (b<<2)+red;
0231 b = (b<<2)+green;
0232 b = (b<<2)+blue;
0233 WriteByte(b);
0234 }
0235 }
0236
0237 } else if(a_nbit==rgb_4) {
0238 int nbyte4 = (a_width * 3)/2;
0239 nbyte4 /=3;
0240 nbyte4 *=3;
0241 Uint col_max = (nbyte4 * 2)/3;
0242 // 4 bit for r and g and b.
0243 // rgbs following each other.
0244 in_buffer ("/rgbstr %d string def ",nbyte4);
0245 in_buffer ("%d %d %d ",col_max,a_height,4);
0246 in_buffer ("[ %d 0 0 -%d 0 %d ] ",col_max,a_height,a_height);
0247 in_buffer ("{ currentfile rgbstr readhexstring pop } " );
0248 in_buffer ("false 3 " );
0249 PrintFLN ("colorimage " );
0250 for ( row = 0; row < a_height; row++ ) {
0251 for ( col = 0; col < col_max; col+=2) {
0252 status = a_proc(a_tag,col,row,dr,dg,db)?status:false;
0253 red = (Uchar) ( 15.0F * dr);
0254 green = (Uchar) ( 15.0F * dg);
0255 in_buffer ("%x%x",red,green);
0256 blue = (Uchar) ( 15.0F * db);
0257
0258 status = a_proc(a_tag,col+1,row,dr,dg,db)?status:false;
0259 red = (Uchar) ( 15.0F * dr);
0260 in_buffer ("%x%x",blue,red);
0261 green = (Uchar) ( 15.0F * dg);
0262 blue = (Uchar) ( 15.0F * db);
0263 in_buffer ("%x%x",green,blue);
0264 }
0265 }
0266
0267 } else if(a_nbit==rgb_8) {
0268 int nbyte8 = a_width * 3;
0269 // 8 bit for r and g and b.
0270 in_buffer ("/rgbstr %d string def ",nbyte8);
0271 in_buffer ("%d %d %d ",a_width,a_height,8);
0272 in_buffer ("[ %d 0 0 -%d 0 %d ] ",a_width,a_height,a_height);
0273 in_buffer ("{ currentfile rgbstr readhexstring pop } " );
0274 in_buffer ("false 3 " );
0275 PrintFLN ("colorimage " );
0276 for ( row = 0; row < a_height; row++ ) {
0277 for ( col = 0; col < a_width; col++) {
0278 status = a_proc(a_tag,col,row,dr,dg,db)?status:false;
0279 red = (Uchar) ( 255.0F * dr);
0280 WriteByte (red);
0281 green = (Uchar) ( 255.0F * dg);
0282 WriteByte (green);
0283 blue = (Uchar) ( 255.0F * db);
0284 WriteByte (blue);
0285 }
0286 }
0287 } else {
0288 m_out << "PS_IMAGE :"
0289 << " unknown rgb nbit " << a_nbit
0290 << std::endl;
0291 }
0292 if(!status) {
0293 m_out << "PS_IMAGE :"
0294 << " problem to retrieve some pixel rgb."
0295 << std::endl;
0296 }
0297 PS_RESTORE();
0298 }
0299
0300 protected:
0301 static size_t METAFILE_RECORD_LENGTH() {return 80;}
0302
0303 static float METAFILE_SCALE() {return 1.0f;}
0304
0305 static char* get_date(){
0306 char* string;
0307 time_t d;
0308 ::time(&d);
0309 string = ::ctime(&d);
0310 string[24] = '\0';
0311 return string;
0312 }
0313
0314 static VCol rgb2grey(VCol a_red,VCol a_green,VCol a_blue){
0315 return (0.30f * a_red + 0.59f * a_green + 0.11f * a_blue);
0316 }
0317
0318 bool in_buffer(const char* a_format,...){
0319 va_list args;
0320 va_start(args,a_format);
0321 bool status = vsprintf(m_string,2048,a_format,args);
0322 va_end(args);
0323 if(!status) {
0324 m_out << "tools::wps::in_buffer : overflow." << std::endl;
0325 return false;
0326 }
0327
0328 size_t length = m_string.size();
0329 if(length>METAFILE_RECORD_LENGTH()) {
0330 m_out << "tools::wps::in_buffer : overflow." << std::endl;
0331 return false;
0332 }
0333
0334 size_t nlength = m_number + length;
0335 if(nlength>METAFILE_RECORD_LENGTH()) {
0336 m_buffer[m_number] = '\0';
0337 if(::fprintf(m_file,"%s\n",(char*)m_buffer)<0) {
0338 m_out << "tools::wps::in_buffer : fprintf failed." << std::endl;
0339 }
0340 m_number = 0;
0341 nlength = length;
0342 }
0343 Uchar* pointer = m_buffer + m_number;
0344 ::strcpy((char*)pointer,m_string.c_str());
0345 m_number = nlength;
0346 return true;
0347 }
0348
0349 bool PrintFLN(const char* a_format,...){
0350 va_list args;
0351 va_start(args,a_format);
0352 bool status = vsprintf(m_string,2048,a_format,args);
0353 va_end(args);
0354 if(!status) {
0355 m_out << "tools::wps::PrintFLN : overflow." << std::endl;
0356 return false;
0357 }
0358
0359 // put buffer in file :
0360 if(m_number>0) {
0361 m_buffer[m_number] = '\0';
0362 if(::fprintf(m_file,"%s\n",(char*)m_buffer)<0) {
0363 m_out << "tools::wps::PrintFLN : fprintf failed." << std::endl;
0364 }
0365 m_number = 0;
0366 }
0367 if(::fprintf(m_file,"%s\n",m_string.c_str())<0) {
0368 m_out << "tools::wps::PrintFLN : fprintf failed." << std::endl;
0369 }
0370
0371 return true;
0372 }
0373
0374 void WriteByte(Uchar a_byte){
0375 Uchar h = a_byte / 16;
0376 Uchar l = a_byte % 16;
0377 in_buffer("%x%x",h,l);
0378 }
0379
0380 protected:
0381 std::ostream& m_out;
0382 float m_deviceWidth;
0383 float m_deviceHeight;
0384 unsigned int m_pageNumber;
0385 FILE* m_file;
0386 std::string m_fname;
0387 std::string m_string;
0388 int m_gsave;
0389 Uchar* m_buffer;
0390 size_t m_number;
0391 };
0392
0393 }
0394
0395 #endif