Warning, /include/Geant4/tools/sg/text_hershey 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_sg_text_hershey
0005 #define tools_sg_text_hershey
0006
0007 #include "base_text"
0008 #include "enums"
0009 #include "strings"
0010 #include "render_action"
0011 #include "pick_action"
0012 #include "bbox_action"
0013 #include "gstos"
0014 #include "sf_string"
0015
0016 #include "../hershey"
0017 #include "../lina/box_3f"
0018 #include "../mnmx"
0019
0020 namespace tools {
0021 namespace sg {
0022
0023 class hchar {
0024 #ifdef TOOLS_MEM
0025 TOOLS_SCLASS(tools::sg::hchar)
0026 #endif
0027 public:
0028 hchar()
0029 :m_char(0)
0030 ,m_font(sg::latin)
0031 ,m_y_move(none)
0032 ,m_back(false)
0033 ,m_bar(false)
0034 ,m_cr(false)
0035 {
0036 #ifdef TOOLS_MEM
0037 mem::increment(s_class().c_str());
0038 #endif
0039 }
0040 virtual ~hchar(){
0041 #ifdef TOOLS_MEM
0042 mem::decrement(s_class().c_str());
0043 #endif
0044 }
0045 public:
0046 hchar(const hchar& aFrom)
0047 :m_char(aFrom.m_char)
0048 ,m_font(aFrom.m_font)
0049 ,m_y_move(aFrom.m_y_move)
0050 ,m_back(aFrom.m_back)
0051 ,m_bar(aFrom.m_bar)
0052 ,m_cr(aFrom.m_cr)
0053 {
0054 #ifdef TOOLS_MEM
0055 mem::increment(s_class().c_str());
0056 #endif
0057 }
0058 hchar& operator=(const hchar& aFrom) {
0059 m_char = aFrom.m_char;
0060 m_font = aFrom.m_font;
0061 m_y_move = aFrom.m_y_move;
0062 m_back = aFrom.m_back;
0063 m_bar = aFrom.m_bar;
0064 m_cr = aFrom.m_cr;
0065 return *this;
0066 }
0067 public:
0068 enum e_move {
0069 none,
0070 up,
0071 down
0072 };
0073 public:
0074 char m_char;
0075 font_type m_font;
0076 e_move m_y_move;
0077 bool m_back;
0078 bool m_bar;
0079 bool m_cr;
0080 };
0081
0082 class text_hershey : public base_text, public gstos {
0083 public:
0084 TOOLS_NODE(text_hershey,tools::sg::text_hershey,base_text)
0085 public:
0086 sf_string encoding;
0087 sf_enum<font_type> font;
0088 public:
0089 virtual const desc_fields& node_desc_fields() const {
0090 TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::text_hershey)
0091 static const desc_fields s_v(parent::node_desc_fields(),2, //WARNING : take care of count.
0092 TOOLS_ARG_FIELD_DESC(encoding),
0093 TOOLS_ARG_FIELD_DESC(font)
0094 );
0095 return s_v;
0096 }
0097 private:
0098 void add_fields(){
0099 add_field(&encoding);
0100 add_field(&font);
0101 }
0102 protected: //gstos
0103 virtual unsigned int create_gsto(std::ostream&,sg::render_manager& a_mgr) {
0104 std::vector<float> gsto_data;
0105
0106 {size_t npts = m_segs.size()/2; //2 coords
0107 size_t ngsto = npts*3; //3 coords.
0108 size_t sz = gsto_data.size();
0109 gsto_data.resize(sz+ngsto);
0110 float* pxyz = vec_data<float>(gsto_data)+sz;
0111 const float* data = vec_data<float>(m_segs);
0112 gl::cvt_2to3(npts,data,pxyz);}
0113
0114 m_gsto_sz = gsto_data.size();
0115
0116 if(gsto_data.empty()) return 0;
0117
0118 return a_mgr.create_gsto_from_data(gsto_data);
0119 }
0120 public:
0121 virtual void render(render_action& a_action) {
0122 if(touched()) {
0123 update_sg();
0124 reset_touched();
0125 }
0126 const state& state = a_action.state();
0127 if(state.m_use_gsto) {
0128 unsigned int _id = get_gsto_id(a_action.out(),a_action.render_manager());
0129 if(_id) {
0130 a_action.begin_gsto(_id);
0131 a_action.draw_gsto_v(gl::lines(),m_gsto_sz/3,0);
0132 a_action.end_gsto();
0133 return;
0134
0135 } else { //!_id
0136 // use immediate rendering.
0137 }
0138
0139 } else {
0140 clean_gstos(&a_action.render_manager());
0141 }
0142
0143 // immediate rendering :
0144 a_action.draw_vertex_array_xy(gl::lines(),m_segs);
0145 }
0146
0147 virtual void pick(pick_action& a_action) {
0148 if(touched()) {
0149 update_sg();
0150 reset_touched();
0151 }
0152 a_action.add__lines_xy(*this,m_segs,true);
0153 }
0154
0155 virtual void bbox(bbox_action& a_action) {
0156 if(touched()) {
0157 update_sg();
0158 reset_touched();
0159 }
0160
0161 float x,y;
0162 std::vector<float>::const_iterator it;
0163 for(it=m_segs.begin();it!=m_segs.end();) {
0164 x = *it;it++;
0165 y = *it;it++;
0166 a_action.add_one_point(x,y,0);
0167 }
0168 }
0169
0170 public:
0171 text_hershey()
0172 :parent()
0173 ,encoding(encoding_none())
0174 ,font(sg::latin)
0175 ,m_gsto_sz(0)
0176 {
0177 add_fields();
0178 }
0179 virtual ~text_hershey(){}
0180 public:
0181 text_hershey(const text_hershey& a_from)
0182 :parent(a_from)
0183 ,gstos(a_from)
0184 ,encoding(a_from.encoding)
0185 ,font(a_from.font)
0186 ,m_gsto_sz(0)
0187 {
0188 add_fields();
0189 }
0190 text_hershey& operator=(const text_hershey& a_from){
0191 parent::operator=(a_from);
0192 gstos::operator=(a_from);
0193 encoding = a_from.encoding;
0194 font = a_from.font;
0195 return *this;
0196 }
0197 public: //sg::base_text :
0198 virtual void get_bounds(float a_height,
0199 float& a_mn_x,float& a_mn_y,float& a_mn_z,
0200 float& a_mx_x,float& a_mx_y,float& a_mx_z) const {
0201 get_bounds(a_height,encoding.value(),font.value(),
0202 strings.values(),
0203 a_mn_x,a_mn_y,a_mn_z,
0204 a_mx_x,a_mx_y,a_mx_z);
0205 }
0206 virtual float ascent(float a_height) const {
0207 // '/' seems to be the char with the max ascent.
0208 // NOTE : If 'A', the ascent = height.value().
0209 float mn_x,mn_y,mn_z;
0210 float mx_x,mx_y,mx_z;
0211 get_char_bound('/',sg::latin,a_height,false,
0212 mn_x,mn_y,mn_z,
0213 mx_x,mx_y,mx_z);
0214 return mx_y;
0215 }
0216 virtual float y_advance(float a_height) const {
0217 float HEIGHT = a_height;
0218 return 2 * HEIGHT; //Y_ADVANCE
0219 }
0220
0221 public:
0222 virtual float descent(float a_height) const {return _descent(a_height);}
0223
0224 virtual bool truncate(const std::string& a_string,float a_height,float a_cut_width,std::string& a_out) const {
0225 return _truncate(a_string,a_height,font.value(),a_cut_width,a_out);
0226 }
0227
0228 public:
0229 static void get_bounds(float a_height,
0230 const std::string& a_encoding,
0231 font_type a_font,
0232 const std::vector<std::string>& a_ss,
0233 float& a_mn_x,float& a_mn_y,float& a_mn_z,
0234 float& a_mx_x,float& a_mx_y,float& a_mx_z){
0235 if(a_ss.size()) {
0236 float HEIGHT = a_height;
0237 float Y_ADVANCE = 2 * HEIGHT;
0238 float width = 0;
0239 float Y = 0;
0240 std::vector<float> dummy;
0241 tools_vforcit(std::string,a_ss,it) {
0242 float XL = 0;
0243 string_segs(false,*it,a_height,a_encoding,a_font,XL,Y,dummy,false);
0244 Y -= Y_ADVANCE;
0245 width = mx<float>(width,XL);
0246 }
0247
0248 a_mn_x = 0;
0249 a_mn_y = -Y_ADVANCE*(a_ss.size()-1)-_descent(a_height);
0250 a_mn_z = 0;
0251 a_mx_x = width;
0252 a_mx_y = HEIGHT;
0253 a_mx_z = 0;
0254 } else {
0255 box_3f_make_empty(a_mn_x,a_mn_y,a_mn_z,a_mx_x,a_mx_y,a_mx_z);
0256 }
0257 }
0258
0259 static void get_bounds(float a_height,
0260 const std::string& a_encoding,
0261 font_type a_font,
0262 const std::string& a_s,
0263 float& a_mn_x,float& a_mn_y,float& a_mn_z,
0264 float& a_mx_x,float& a_mx_y,float& a_mx_z){
0265 float HEIGHT = a_height;
0266 float Y_ADVANCE = 2 * HEIGHT;
0267 float width = 0;
0268 float Y = 0;
0269 std::vector<float> dummy;
0270 float XL = 0;
0271 string_segs(false,a_s,a_height,a_encoding,a_font,XL,Y,dummy,false);
0272 Y -= Y_ADVANCE;
0273 width = mx<float>(width,XL);
0274
0275 a_mn_x = 0;
0276 a_mn_y = -_descent(a_height);
0277 a_mn_z = 0;
0278 a_mx_x = width;
0279 a_mx_y = HEIGHT;
0280 a_mx_z = 0;
0281 }
0282
0283 protected:
0284 void update_sg() {
0285 clean_gstos();
0286 m_segs.clear();
0287 get_segments(m_segs);
0288 }
0289
0290 void get_segments(std::vector<float>& a_segs) const {
0291
0292 float Y = 0;
0293 if( (vjust.value()==sg::middle) ||
0294 (vjust.value()==sg::top) ){
0295 float mn_x,mn_y,mn_z;
0296 float mx_x,mx_y,mx_z;
0297 get_bounds(height.value(),mn_x,mn_y,mn_z,mx_x,mx_y,mx_z);
0298 float szy = mx_y - mn_y;
0299
0300 if(vjust.value()==sg::middle) {
0301 Y -= 0.5F * szy;
0302 } else if(vjust.value()==sg::top) {
0303 Y -= szy;
0304 }
0305 }
0306
0307 float HEIGHT = height.value();
0308 float Y_ADVANCE = 2 * HEIGHT;
0309
0310 const std::string& encod = encoding.value();
0311
0312 const std::vector<std::string>& ss = strings.values();
0313 tools_vforcit(std::string,ss,it) {
0314
0315 float X = 0;
0316 if( (hjust.value()==sg::center) ||
0317 (hjust.value()==sg::right) ){
0318 float mn_x,mn_y,mn_z;
0319 float mx_x,mx_y,mx_z;
0320 get_bounds(height,encoding.value(),font,*it,
0321 mn_x,mn_y,mn_z,mx_x,mx_y,mx_z);
0322 float szx = mx_x - mn_x;
0323
0324 if(hjust.value()==sg::center) {
0325 X -= 0.5F * szx;
0326 } else if(hjust.value()==sg::right) {
0327 X -= szx;
0328 }
0329 }
0330
0331 string_segs(true,*it,HEIGHT,encod,font.value(),X,Y,a_segs,true);
0332 Y -= Y_ADVANCE;
0333 }
0334 }
0335 protected:
0336 static float _descent(float a_height) {
0337 // '/' seems to be the char with the max descent.
0338 float mn_x,mn_y,mn_z;
0339 float mx_x,mx_y,mx_z;
0340 get_char_bound('/',sg::latin,a_height,false,
0341 mn_x,mn_y,mn_z,
0342 mx_x,mx_y,mx_z);
0343 return -mn_y; //return then a positive number.
0344 }
0345
0346 static bool _truncate(const std::string& a_string,
0347 float a_height,
0348 font_type a_font,float a_cut_width,
0349 std::string& a_out) {
0350 //It does not take into account encoding.
0351
0352 a_out.clear();
0353
0354 float width = 0;
0355
0356 const unsigned int mx_poly = 4;
0357 const unsigned int mx_point = 160;
0358
0359 int max_point[mx_poly];
0360 float xp[mx_point];
0361 float yp[mx_point];
0362
0363 tools_sforcit(a_string,it) {
0364
0365 float cwidth;
0366 int number;
0367 if (a_font==sg::greek) {
0368 hershey::greek_char_points(*it,a_height,number,max_point,xp,yp,cwidth);
0369 } else if (a_font==sg::special) {
0370 hershey::special_char_points(*it,a_height,number,max_point,xp,yp,cwidth);
0371 } else {
0372 hershey::latin_char_points(*it,a_height,number,max_point,xp,yp,cwidth);
0373 }
0374
0375 float advance = cwidth + a_height * 0.01F;
0376
0377 if((width+cwidth)>=a_cut_width) return true;
0378 a_out += *it;
0379 width += advance;
0380 }
0381
0382 return true;
0383 }
0384
0385 static void get_char_bound(char a_char,
0386 font_type a_font,
0387 float a_scale,bool a_bar,
0388 float& a_mn_x,float& a_mn_y,float& a_mn_z,
0389 float& a_mx_x,float& a_mx_y,float& a_mx_z){
0390 box_3f_make_empty(a_mn_x,a_mn_y,a_mn_z,a_mx_x,a_mx_y,a_mx_z);
0391
0392 const unsigned int mx_poly = 4;
0393 const unsigned int mx_point = 160;
0394
0395 int max_point[mx_poly];
0396 float xp[mx_point];
0397 float yp[mx_point];
0398
0399 int number;
0400 float width;
0401 if (a_font==sg::greek) {
0402 hershey::greek_char_points(a_char,a_scale,number,max_point,xp,yp,width);
0403 } else if (a_font==sg::special) {
0404 hershey::special_char_points(a_char,a_scale,number,max_point,xp,yp,width);
0405 } else {
0406 hershey::latin_char_points(a_char,a_scale,number,max_point,xp,yp,width);
0407 }
0408
0409 float ymax = 0;
0410
0411 int ipoint = 0;
0412 for (int ipoly=0;ipoly<number;ipoly++) {
0413 int pointn = max_point[ipoly];
0414 if(pointn>0) {
0415 for(int count=0;count<pointn-1;count++) {
0416 ymax = mx<float>(ymax,yp[ipoint]);
0417 box_3f_extend_by(a_mn_x,a_mn_y,a_mn_z,a_mx_x,a_mx_y,a_mx_z,xp[ipoint],yp[ipoint],0);
0418
0419 ymax = mx<float>(ymax,yp[ipoint+1]);
0420 box_3f_extend_by(a_mn_x,a_mn_y,a_mn_z,a_mx_x,a_mx_y,a_mx_z,xp[ipoint+1],yp[ipoint+1],0);
0421
0422 ipoint ++;
0423 }
0424 ipoint ++;
0425 }
0426 }
0427
0428 if(a_bar) { //Draw a bar on top of the character.
0429 float xbar = 0;
0430 float ybar = ymax * 1.3F;
0431 box_3f_extend_by(a_mn_x,a_mn_y,a_mn_z,a_mx_x,a_mx_y,a_mx_z,xbar,ybar,0);
0432 box_3f_extend_by(a_mn_x,a_mn_y,a_mn_z,a_mx_x,a_mx_y,a_mx_z,xbar+width,ybar,0);
0433 }
0434 }
0435
0436 static void string_segs(
0437 bool aGEN_POINTS // false = advance only.
0438 ,const std::string& a_string
0439 ,float a_height
0440 ,const std::string& a_encoding
0441 ,font_type a_font
0442 ,float& aX
0443 ,float& aY
0444 ,std::vector<float>& a_segs
0445 ,bool a_fill_segs
0446 ){
0447 float oldX = 0;
0448 float HEIGHT = a_height;
0449
0450 bool encod_PAW = (a_encoding==encoding_PAW()?true:false);
0451
0452 sencoded sed;
0453 if(encod_PAW) decode_PAW(a_string,sed);
0454 else decode_plain(a_string,sed);
0455
0456 tools_vforcit(hchar,sed,it) {
0457 const hchar& hc = *it;
0458
0459 font_type hershey_font = hc.m_font;
0460 if(encod_PAW) {
0461 hershey_font = hc.m_font;
0462 } else {
0463 hershey_font = a_font;
0464 }
0465
0466 float scale = HEIGHT;
0467 float ymove = 0;
0468 if(hc.m_y_move==hchar::up) {
0469 scale = HEIGHT*0.6F;
0470 ymove = HEIGHT*0.6F;
0471 } else if(hc.m_y_move==hchar::down) {
0472 scale = HEIGHT*0.6F;
0473 ymove = -HEIGHT*0.6F;
0474 }
0475 if(hc.m_back) aX = oldX;
0476 oldX = aX;
0477 //FIXME : bar
0478 aY += ymove;
0479
0480 float advance = char_segs(aGEN_POINTS,hc.m_char,hershey_font,scale,hc.m_bar,aX,aY,a_segs,a_fill_segs) + HEIGHT * 0.01F;
0481
0482 aX += advance;
0483
0484 aY -= ymove;
0485 }
0486 }
0487
0488 static float char_segs(
0489 bool aGEN_POINTS // false = advance only.
0490 ,char a_char
0491 ,font_type a_font
0492 ,float a_scale
0493 ,bool aBar
0494 ,float aX
0495 ,float aY
0496 ,std::vector<float>& a_segs
0497 ,bool a_fill_segs
0498 ){
0499 const unsigned int mx_poly = 8;
0500 const unsigned int mx_point = 160;
0501
0502 int max_point[mx_poly];
0503 float xp[mx_point];
0504 float yp[mx_point];
0505
0506 int number;
0507 float width;
0508 if (a_font==sg::greek) {
0509 hershey::greek_char_points(a_char,a_scale,number,max_point,xp,yp,width);
0510 } else if (a_font==sg::special) {
0511 hershey::special_char_points(a_char,a_scale,number,max_point,xp,yp,width);
0512 } else {
0513 hershey::latin_char_points(a_char,a_scale,number,max_point,xp,yp,width);
0514 }
0515 if(!aGEN_POINTS) return width;
0516
0517 float ymax = 0;
0518
0519 int ipoint = 0;
0520 int pointn;
0521 for (int ipoly=0;ipoly<number;ipoly++) {
0522 pointn = max_point[ipoly];
0523 if(pointn>0) {
0524 for(int count=0;count<pointn-1;count++) {
0525 ymax = mx<float>(ymax,yp[ipoint]);
0526 if(a_fill_segs) {
0527 a_segs.push_back(aX+xp[ipoint]);
0528 a_segs.push_back(aY+yp[ipoint]);
0529 }
0530 ymax = mx<float>(ymax,yp[ipoint+1]);
0531 if(a_fill_segs) {
0532 a_segs.push_back(aX+xp[ipoint+1]);
0533 a_segs.push_back(aY+yp[ipoint+1]);
0534 }
0535 ipoint ++;
0536 }
0537 ipoint ++;
0538 }
0539 }
0540
0541 if(aBar) { //Draw a bar on top of the character.
0542 float xbar = 0;
0543 float ybar = ymax * 1.3F;
0544
0545 if(a_fill_segs) {
0546 a_segs.push_back(aX+xbar);
0547 a_segs.push_back(aY+ybar);
0548
0549 a_segs.push_back(aX+xbar+width);
0550 a_segs.push_back(aY+ybar);
0551 }
0552 }
0553
0554 return width;
0555 }
0556
0557 typedef std::vector<hchar> sencoded;
0558
0559 static void decode_plain(const std::string& a_s,sencoded& a_sed){
0560 a_sed.clear();
0561 tools_sforcit(a_s,it) {
0562 hchar hc;
0563 hc.m_char = *it;
0564 a_sed.push_back(hc);
0565 }
0566 if(a_sed.size()) a_sed[a_sed.size()-1].m_cr = true;
0567 }
0568 ///////////////////////////////////////////////////////////////////////////
0569 /// PAW encoding //////////////////////////////////////////////////////////
0570 ///////////////////////////////////////////////////////////////////////////
0571 // PAW control characters :
0572 // [ go to greek (roman = default)
0573 // ] end of greek
0574 // " go to special
0575 // # end of special
0576 // ! go to normal level of script
0577 // ^ go to superscript
0578 // ? go to subscript
0579 // & backscpace one charachter
0580 // < go to lower case
0581 // > go to upper case (default)
0582 // Extension :
0583 // | draw a bar over one character
0584 // Found in PAW manual Version 1.14 (July 1992), page 178, 180.
0585 ///////////////////////////////////////////////////////////////////////////
0586 static void decode_PAW(const std::string& a_s,sencoded& a_sed){
0587 a_sed.clear();
0588
0589 font_type hershey_font = sg::latin;
0590 hchar::e_move move = hchar::none;
0591 bool back = false;
0592 bool bar = false;
0593 //bool upper = true; //to be done.
0594
0595 tools_sforcit(a_s,it) {
0596 char c = *it;
0597 // Control characters :
0598 if(c=='[') {
0599 hershey_font = sg::greek;
0600 continue;
0601 } else if(c==']') {
0602 hershey_font = sg::latin;
0603 continue;
0604 } else if(c=='"') {
0605 hershey_font = sg::special;
0606 continue;
0607 } else if(c=='#') {
0608 hershey_font = sg::latin;
0609 continue;
0610 } else if(c=='!') {
0611 move = hchar::none;
0612 continue;
0613 } else if(c=='^') {
0614 move = hchar::up;
0615 continue;
0616 } else if(c=='?') {
0617 move = hchar::down;
0618 continue;
0619 } else if(c=='&') {
0620 back = true;
0621 continue;
0622 } else if(c=='<') {
0623 //upper = false;
0624 continue;
0625 } else if(c=='>') {
0626 //upper = true;
0627 continue;
0628 }
0629
0630 hchar hc;
0631 hc.m_y_move = move;
0632 hc.m_back = back;
0633 hc.m_bar = bar;
0634 hc.m_font = hershey_font;
0635 hc.m_char = c;
0636
0637 a_sed.push_back(hc);
0638
0639 back = false;
0640 bar = false;
0641 }
0642
0643 if(a_sed.size()) a_sed[a_sed.size()-1].m_cr = true;
0644 }
0645
0646 protected:
0647 std::vector<float> m_segs; //list of [begin,end]
0648 size_t m_gsto_sz;
0649 };
0650
0651 }}
0652
0653 #endif