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