Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights 2 // See the file tools.license for terms. 3 4 #ifndef tools_sg_text_hershey 5 #define tools_sg_text_hershey 6 7 #include "base_text" 8 #include "enums" 9 #include "strings" 10 #include "render_action" 11 #include "pick_action" 12 #include "bbox_action" 13 #include "gstos" 14 #include "sf_string" 15 16 #include "../hershey" 17 #include "../lina/box_3f" 18 #include "../mnmx" 19 20 namespace tools { 21 namespace sg { 22 23 class hchar { 24 #ifdef TOOLS_MEM 25 TOOLS_SCLASS(tools::sg::hchar) 26 #endif 27 public: 28 hchar() 29 :m_char(0) 30 ,m_font(sg::latin) 31 ,m_y_move(none) 32 ,m_back(false) 33 ,m_bar(false) 34 ,m_cr(false) 35 { 36 #ifdef TOOLS_MEM 37 mem::increment(s_class().c_str()); 38 #endif 39 } 40 virtual ~hchar(){ 41 #ifdef TOOLS_MEM 42 mem::decrement(s_class().c_str()); 43 #endif 44 } 45 public: 46 hchar(const hchar& aFrom) 47 :m_char(aFrom.m_char) 48 ,m_font(aFrom.m_font) 49 ,m_y_move(aFrom.m_y_move) 50 ,m_back(aFrom.m_back) 51 ,m_bar(aFrom.m_bar) 52 ,m_cr(aFrom.m_cr) 53 { 54 #ifdef TOOLS_MEM 55 mem::increment(s_class().c_str()); 56 #endif 57 } 58 hchar& operator=(const hchar& aFrom) { 59 m_char = aFrom.m_char; 60 m_font = aFrom.m_font; 61 m_y_move = aFrom.m_y_move; 62 m_back = aFrom.m_back; 63 m_bar = aFrom.m_bar; 64 m_cr = aFrom.m_cr; 65 return *this; 66 } 67 public: 68 enum e_move { 69 none, 70 up, 71 down 72 }; 73 public: 74 char m_char; 75 font_type m_font; 76 e_move m_y_move; 77 bool m_back; 78 bool m_bar; 79 bool m_cr; 80 }; 81 82 class text_hershey : public base_text, public 83 public: 84 TOOLS_NODE(text_hershey,tools::sg::text_hers 85 public: 86 sf_string encoding; 87 sf_enum<font_type> font; 88 public: 89 virtual const desc_fields& node_desc_fields( 90 TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::tex 91 static const desc_fields s_v(parent::node_ 92 TOOLS_ARG_FIELD_DESC(encoding), 93 TOOLS_ARG_FIELD_DESC(font) 94 ); 95 return s_v; 96 } 97 private: 98 void add_fields(){ 99 add_field(&encoding); 100 add_field(&font); 101 } 102 protected: //gstos 103 virtual unsigned int create_gsto(std::ostrea 104 std::vector<float> gsto_data; 105 106 {size_t npts = m_segs.size()/2; //2 coords 107 size_t ngsto = npts*3; //3 coords. 108 size_t sz = gsto_data.size(); 109 gsto_data.resize(sz+ngsto); 110 float* pxyz = vec_data<float>(gsto_data)+s 111 const float* data = vec_data<float>(m_segs 112 gl::cvt_2to3(npts,data,pxyz);} 113 114 m_gsto_sz = gsto_data.size(); 115 116 if(gsto_data.empty()) return 0; 117 118 return a_mgr.create_gsto_from_data(gsto_da 119 } 120 public: 121 virtual void render(render_action& a_action) 122 if(touched()) { 123 update_sg(); 124 reset_touched(); 125 } 126 const state& state = a_action.state(); 127 if(state.m_use_gsto) { 128 unsigned int _id = get_gsto_id(a_action. 129 if(_id) { 130 a_action.begin_gsto(_id); 131 a_action.draw_gsto_v(gl::lines(),m_gst 132 a_action.end_gsto(); 133 return; 134 135 } else { //!_id 136 // use immediate rendering. 137 } 138 139 } else { 140 clean_gstos(&a_action.render_manager()); 141 } 142 143 // immediate rendering : 144 a_action.draw_vertex_array_xy(gl::lines(), 145 } 146 147 virtual void pick(pick_action& a_action) { 148 if(touched()) { 149 update_sg(); 150 reset_touched(); 151 } 152 a_action.add__lines_xy(*this,m_segs,true); 153 } 154 155 virtual void bbox(bbox_action& a_action) { 156 if(touched()) { 157 update_sg(); 158 reset_touched(); 159 } 160 161 float x,y; 162 std::vector<float>::const_iterator it; 163 for(it=m_segs.begin();it!=m_segs.end();) { 164 x = *it;it++; 165 y = *it;it++; 166 a_action.add_one_point(x,y,0); 167 } 168 } 169 170 public: 171 text_hershey() 172 :parent() 173 ,encoding(encoding_none()) 174 ,font(sg::latin) 175 ,m_gsto_sz(0) 176 { 177 add_fields(); 178 } 179 virtual ~text_hershey(){} 180 public: 181 text_hershey(const text_hershey& a_from) 182 :parent(a_from) 183 ,gstos(a_from) 184 ,encoding(a_from.encoding) 185 ,font(a_from.font) 186 ,m_gsto_sz(0) 187 { 188 add_fields(); 189 } 190 text_hershey& operator=(const text_hershey& 191 parent::operator=(a_from); 192 gstos::operator=(a_from); 193 encoding = a_from.encoding; 194 font = a_from.font; 195 return *this; 196 } 197 public: //sg::base_text : 198 virtual void get_bounds(float a_height, 199 float& a_mn_x,float& 200 float& a_mx_x,float& 201 get_bounds(a_height,encoding.value(),font. 202 strings.values(), 203 a_mn_x,a_mn_y,a_mn_z, 204 a_mx_x,a_mx_y,a_mx_z); 205 } 206 virtual float ascent(float a_height) const { 207 // '/' seems to be the char with the max a 208 // NOTE : If 'A', the ascent = height.valu 209 float mn_x,mn_y,mn_z; 210 float mx_x,mx_y,mx_z; 211 get_char_bound('/',sg::latin,a_height,fals 212 mn_x,mn_y,mn_z, 213 mx_x,mx_y,mx_z); 214 return mx_y; 215 } 216 virtual float y_advance(float a_height) cons 217 float HEIGHT = a_height; 218 return 2 * HEIGHT; //Y_ADVANCE 219 } 220 221 public: 222 virtual float descent(float a_height) const 223 224 virtual bool truncate(const std::string& a_s 225 return _truncate(a_string,a_height,font.va 226 } 227 228 public: 229 static void get_bounds(float a_height, 230 const std::string& a_ 231 font_type a_font, 232 const std::vector<std 233 float& a_mn_x,float& 234 float& a_mx_x,float& 235 if(a_ss.size()) { 236 float HEIGHT = a_height; 237 float Y_ADVANCE = 2 * HEIGHT; 238 float width = 0; 239 float Y = 0; 240 std::vector<float> dummy; 241 tools_vforcit(std::string,a_ss,it) { 242 float XL = 0; 243 string_segs(false,*it,a_height,a_encod 244 Y -= Y_ADVANCE; 245 width = mx<float>(width,XL); 246 } 247 248 a_mn_x = 0; 249 a_mn_y = -Y_ADVANCE*(a_ss.size()-1)-_des 250 a_mn_z = 0; 251 a_mx_x = width; 252 a_mx_y = HEIGHT; 253 a_mx_z = 0; 254 } else { 255 box_3f_make_empty(a_mn_x,a_mn_y,a_mn_z,a 256 } 257 } 258 259 static void get_bounds(float a_height, 260 const std::string& a_ 261 font_type a_font, 262 const std::string& a_ 263 float& a_mn_x,float& 264 float& a_mx_x,float& 265 float HEIGHT = a_height; 266 float Y_ADVANCE = 2 * HEIGHT; 267 float width = 0; 268 float Y = 0; 269 std::vector<float> dummy; 270 float XL = 0; 271 string_segs(false,a_s,a_height,a_encoding, 272 Y -= Y_ADVANCE; 273 width = mx<float>(width,XL); 274 275 a_mn_x = 0; 276 a_mn_y = -_descent(a_height); 277 a_mn_z = 0; 278 a_mx_x = width; 279 a_mx_y = HEIGHT; 280 a_mx_z = 0; 281 } 282 283 protected: 284 void update_sg() { 285 clean_gstos(); 286 m_segs.clear(); 287 get_segments(m_segs); 288 } 289 290 void get_segments(std::vector<float>& a_segs 291 292 float Y = 0; 293 if( (vjust.value()==sg::middle) || 294 (vjust.value()==sg::top) ){ 295 float mn_x,mn_y,mn_z; 296 float mx_x,mx_y,mx_z; 297 get_bounds(height.value(),mn_x,mn_y,mn_z 298 float szy = mx_y - mn_y; 299 300 if(vjust.value()==sg::middle) { 301 Y -= 0.5F * szy; 302 } else if(vjust.value()==sg::top) { 303 Y -= szy; 304 } 305 } 306 307 float HEIGHT = height.value(); 308 float Y_ADVANCE = 2 * HEIGHT; 309 310 const std::string& encod = encoding.value( 311 312 const std::vector<std::string>& ss = strin 313 tools_vforcit(std::string,ss,it) { 314 315 float X = 0; 316 if( (hjust.value()==sg::center) || 317 (hjust.value()==sg::right) ){ 318 float mn_x,mn_y,mn_z; 319 float mx_x,mx_y,mx_z; 320 get_bounds(height,encoding.value(),fon 321 mn_x,mn_y,mn_z,mx_x,mx_y,mx 322 float szx = mx_x - mn_x; 323 324 if(hjust.value()==sg::center) { 325 X -= 0.5F * szx; 326 } else if(hjust.value()==sg::right) { 327 X -= szx; 328 } 329 } 330 331 string_segs(true,*it,HEIGHT,encod,font.v 332 Y -= Y_ADVANCE; 333 } 334 } 335 protected: 336 static float _descent(float a_height) { 337 // '/' seems to be the char with the max d 338 float mn_x,mn_y,mn_z; 339 float mx_x,mx_y,mx_z; 340 get_char_bound('/',sg::latin,a_height,fals 341 mn_x,mn_y,mn_z, 342 mx_x,mx_y,mx_z); 343 return -mn_y; //return then a positive num 344 } 345 346 static bool _truncate(const std::string& a_s 347 float a_height, 348 font_type a_font,float 349 std::string& a_out) { 350 //It does not take into account encoding. 351 352 a_out.clear(); 353 354 float width = 0; 355 356 const unsigned int mx_poly = 4; 357 const unsigned int mx_point = 160; 358 359 int max_point[mx_poly]; 360 float xp[mx_point]; 361 float yp[mx_point]; 362 363 tools_sforcit(a_string,it) { 364 365 float cwidth; 366 int number; 367 if (a_font==sg::greek) { 368 hershey::greek_char_points(*it,a_heigh 369 } else if (a_font==sg::special) { 370 hershey::special_char_points(*it,a_hei 371 } else { 372 hershey::latin_char_points(*it,a_heigh 373 } 374 375 float advance = cwidth + a_height * 0.01 376 377 if((width+cwidth)>=a_cut_width) return t 378 a_out += *it; 379 width += advance; 380 } 381 382 return true; 383 } 384 385 static void get_char_bound(char a_char, 386 font_type a_font, 387 float a_scale,boo 388 float& a_mn_x,flo 389 float& a_mx_x,flo 390 box_3f_make_empty(a_mn_x,a_mn_y,a_mn_z,a_m 391 392 const unsigned int mx_poly = 4; 393 const unsigned int mx_point = 160; 394 395 int max_point[mx_poly]; 396 float xp[mx_point]; 397 float yp[mx_point]; 398 399 int number; 400 float width; 401 if (a_font==sg::greek) { 402 hershey::greek_char_points(a_char,a_scal 403 } else if (a_font==sg::special) { 404 hershey::special_char_points(a_char,a_sc 405 } else { 406 hershey::latin_char_points(a_char,a_scal 407 } 408 409 float ymax = 0; 410 411 int ipoint = 0; 412 for (int ipoly=0;ipoly<number;ipoly++) { 413 int pointn = max_point[ipoly]; 414 if(pointn>0) { 415 for(int count=0;count<pointn-1;count++ 416 ymax = mx<float>(ymax,yp[ipoint]); 417 box_3f_extend_by(a_mn_x,a_mn_y,a_mn_ 418 419 ymax = mx<float>(ymax,yp[ipoint+1]); 420 box_3f_extend_by(a_mn_x,a_mn_y,a_mn_ 421 422 ipoint ++; 423 } 424 ipoint ++; 425 } 426 } 427 428 if(a_bar) { //Draw a bar on top of the cha 429 float xbar = 0; 430 float ybar = ymax * 1.3F; 431 box_3f_extend_by(a_mn_x,a_mn_y,a_mn_z,a_ 432 box_3f_extend_by(a_mn_x,a_mn_y,a_mn_z,a_ 433 } 434 } 435 436 static void string_segs( 437 bool aGEN_POINTS // false = advance only. 438 ,const std::string& a_string 439 ,float a_height 440 ,const std::string& a_encoding 441 ,font_type a_font 442 ,float& aX 443 ,float& aY 444 ,std::vector<float>& a_segs 445 ,bool a_fill_segs 446 ){ 447 float oldX = 0; 448 float HEIGHT = a_height; 449 450 bool encod_PAW = (a_encoding==encoding_PAW 451 452 sencoded sed; 453 if(encod_PAW) decode_PAW(a_string,sed); 454 else decode_plain(a_string,sed); 455 456 tools_vforcit(hchar,sed,it) { 457 const hchar& hc = *it; 458 459 font_type hershey_font = hc.m_font; 460 if(encod_PAW) { 461 hershey_font = hc.m_font; 462 } else { 463 hershey_font = a_font; 464 } 465 466 float scale = HEIGHT; 467 float ymove = 0; 468 if(hc.m_y_move==hchar::up) { 469 scale = HEIGHT*0.6F; 470 ymove = HEIGHT*0.6F; 471 } else if(hc.m_y_move==hchar::down) { 472 scale = HEIGHT*0.6F; 473 ymove = -HEIGHT*0.6F; 474 } 475 if(hc.m_back) aX = oldX; 476 oldX = aX; 477 //FIXME : bar 478 aY += ymove; 479 480 float advance = char_segs(aGEN_POINTS,hc 481 482 aX += advance; 483 484 aY -= ymove; 485 } 486 } 487 488 static float char_segs( 489 bool aGEN_POINTS // false = advance only. 490 ,char a_char 491 ,font_type a_font 492 ,float a_scale 493 ,bool aBar 494 ,float aX 495 ,float aY 496 ,std::vector<float>& a_segs 497 ,bool a_fill_segs 498 ){ 499 const unsigned int mx_poly = 8; 500 const unsigned int mx_point = 160; 501 502 int max_point[mx_poly]; 503 float xp[mx_point]; 504 float yp[mx_point]; 505 506 int number; 507 float width; 508 if (a_font==sg::greek) { 509 hershey::greek_char_points(a_char,a_scal 510 } else if (a_font==sg::special) { 511 hershey::special_char_points(a_char,a_sc 512 } else { 513 hershey::latin_char_points(a_char,a_scal 514 } 515 if(!aGEN_POINTS) return width; 516 517 float ymax = 0; 518 519 int ipoint = 0; 520 int pointn; 521 for (int ipoly=0;ipoly<number;ipoly++) { 522 pointn = max_point[ipoly]; 523 if(pointn>0) { 524 for(int count=0;count<pointn-1;count++ 525 ymax = mx<float>(ymax,yp[ipoint]); 526 if(a_fill_segs) { 527 a_segs.push_back(aX+xp[ipoint]); 528 a_segs.push_back(aY+yp[ipoint]); 529 } 530 ymax = mx<float>(ymax,yp[ipoint+1]); 531 if(a_fill_segs) { 532 a_segs.push_back(aX+xp[ipoint+1]); 533 a_segs.push_back(aY+yp[ipoint+1]); 534 } 535 ipoint ++; 536 } 537 ipoint ++; 538 } 539 } 540 541 if(aBar) { //Draw a bar on top of the char 542 float xbar = 0; 543 float ybar = ymax * 1.3F; 544 545 if(a_fill_segs) { 546 a_segs.push_back(aX+xbar); 547 a_segs.push_back(aY+ybar); 548 549 a_segs.push_back(aX+xbar+width); 550 a_segs.push_back(aY+ybar); 551 } 552 } 553 554 return width; 555 } 556 557 typedef std::vector<hchar> sencoded; 558 559 static void decode_plain(const std::string& 560 a_sed.clear(); 561 tools_sforcit(a_s,it) { 562 hchar hc; 563 hc.m_char = *it; 564 a_sed.push_back(hc); 565 } 566 if(a_sed.size()) a_sed[a_sed.size()-1].m_c 567 } 568 //////////////////////////////////////////// 569 /// PAW encoding /////////////////////////// 570 //////////////////////////////////////////// 571 // PAW control characters : 572 // [ go to greek (roman = default) 573 // ] end of greek 574 // " go to special 575 // # end of special 576 // ! go to normal level of script 577 // ^ go to superscript 578 // ? go to subscript 579 // & backscpace one charachter 580 // < go to lower case 581 // > go to upper case (default) 582 // Extension : 583 // | draw a bar over one character 584 // Found in PAW manual Version 1.14 (July 19 585 //////////////////////////////////////////// 586 static void decode_PAW(const std::string& a_ 587 a_sed.clear(); 588 589 font_type hershey_font = sg::latin; 590 hchar::e_move move = hchar::none; 591 bool back = false; 592 bool bar = false; 593 //bool upper = true; //to be done. 594 595 tools_sforcit(a_s,it) { 596 char c = *it; 597 // Control characters : 598 if(c=='[') { 599 hershey_font = sg::greek; 600 continue; 601 } else if(c==']') { 602 hershey_font = sg::latin; 603 continue; 604 } else if(c=='"') { 605 hershey_font = sg::special; 606 continue; 607 } else if(c=='#') { 608 hershey_font = sg::latin; 609 continue; 610 } else if(c=='!') { 611 move = hchar::none; 612 continue; 613 } else if(c=='^') { 614 move = hchar::up; 615 continue; 616 } else if(c=='?') { 617 move = hchar::down; 618 continue; 619 } else if(c=='&') { 620 back = true; 621 continue; 622 } else if(c=='<') { 623 //upper = false; 624 continue; 625 } else if(c=='>') { 626 //upper = true; 627 continue; 628 } 629 630 hchar hc; 631 hc.m_y_move = move; 632 hc.m_back = back; 633 hc.m_bar = bar; 634 hc.m_font = hershey_font; 635 hc.m_char = c; 636 637 a_sed.push_back(hc); 638 639 back = false; 640 bar = false; 641 } 642 643 if(a_sed.size()) a_sed[a_sed.size()-1].m_c 644 } 645 646 protected: 647 std::vector<float> m_segs; //list of [begin, 648 size_t m_gsto_sz; 649 }; 650 651 }} 652 653 #endif