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 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