Back to home page

EIC code displayed by LXR

 
 

    


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