Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/tools/sg/text_hershey

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
  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 gstos {
 83 public:
 84   TOOLS_NODE(text_hershey,tools::sg::text_hershey,base_text)
 85 public:
 86   sf_string encoding;
 87   sf_enum<font_type> font;
 88 public:
 89   virtual const desc_fields& node_desc_fields() const {
 90     TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::text_hershey)
 91     static const desc_fields s_v(parent::node_desc_fields(),2, //WARNING : take care of count.
 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::ostream&,sg::render_manager& a_mgr) {
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)+sz;
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_data);
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.out(),a_action.render_manager());
129       if(_id) {
130         a_action.begin_gsto(_id);
131         a_action.draw_gsto_v(gl::lines(),m_gsto_sz/3,0);
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(),m_segs);
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& a_from){
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& a_mn_y,float& a_mn_z,
200                           float& a_mx_x,float& a_mx_y,float& a_mx_z) const {
201     get_bounds(a_height,encoding.value(),font.value(),
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 ascent.
208     // NOTE : If 'A', the ascent = height.value().
209     float mn_x,mn_y,mn_z;
210     float mx_x,mx_y,mx_z;
211     get_char_bound('/',sg::latin,a_height,false,
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) const {
217     float HEIGHT = a_height;
218     return 2 * HEIGHT; //Y_ADVANCE
219   }
220 
221 public:
222   virtual float descent(float a_height) const {return _descent(a_height);}
223 
224   virtual bool truncate(const std::string& a_string,float a_height,float a_cut_width,std::string& a_out) const {
225     return _truncate(a_string,a_height,font.value(),a_cut_width,a_out);
226   }
227 
228 public:
229   static void get_bounds(float a_height,
230                          const std::string& a_encoding,
231                          font_type a_font,
232                          const std::vector<std::string>& a_ss,
233                          float& a_mn_x,float& a_mn_y,float& a_mn_z,
234                          float& a_mx_x,float& a_mx_y,float& a_mx_z){
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_encoding,a_font,XL,Y,dummy,false);
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)-_descent(a_height);
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_mx_x,a_mx_y,a_mx_z);
256     }
257   }
258 
259   static void get_bounds(float a_height,
260                          const std::string& a_encoding,
261                          font_type a_font,
262                          const std::string& a_s,
263                          float& a_mn_x,float& a_mn_y,float& a_mn_z,
264                          float& a_mx_x,float& a_mx_y,float& a_mx_z){
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,a_font,XL,Y,dummy,false);
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) const {
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,mx_x,mx_y,mx_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 = strings.values();
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(),font,*it,
321                    mn_x,mn_y,mn_z,mx_x,mx_y,mx_z);
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.value(),X,Y,a_segs,true);
332       Y -= Y_ADVANCE;
333     }
334   }
335 protected:
336   static float _descent(float a_height) {
337     // '/' seems to be the char with the max descent.
338     float mn_x,mn_y,mn_z;
339     float mx_x,mx_y,mx_z;
340     get_char_bound('/',sg::latin,a_height,false,
341                    mn_x,mn_y,mn_z,
342                    mx_x,mx_y,mx_z);
343     return -mn_y; //return then a positive number.
344   }
345 
346   static bool _truncate(const std::string& a_string,
347                         float a_height,
348                         font_type a_font,float a_cut_width,
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_height,number,max_point,xp,yp,cwidth);
369       } else if (a_font==sg::special) {
370         hershey::special_char_points(*it,a_height,number,max_point,xp,yp,cwidth);
371       } else {
372         hershey::latin_char_points(*it,a_height,number,max_point,xp,yp,cwidth);
373       }
374 
375       float advance = cwidth + a_height * 0.01F;
376 
377       if((width+cwidth)>=a_cut_width) return true;
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,bool a_bar,
388                              float& a_mn_x,float& a_mn_y,float& a_mn_z,
389                              float& a_mx_x,float& a_mx_y,float& a_mx_z){
390     box_3f_make_empty(a_mn_x,a_mn_y,a_mn_z,a_mx_x,a_mx_y,a_mx_z);
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_scale,number,max_point,xp,yp,width);
403     } else if (a_font==sg::special) {
404       hershey::special_char_points(a_char,a_scale,number,max_point,xp,yp,width);
405     } else {
406       hershey::latin_char_points(a_char,a_scale,number,max_point,xp,yp,width);
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_z,a_mx_x,a_mx_y,a_mx_z,xp[ipoint],yp[ipoint],0);
418 
419           ymax = mx<float>(ymax,yp[ipoint+1]);
420           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);
421 
422           ipoint ++;
423         }
424         ipoint ++;
425       }
426     }
427 
428     if(a_bar) { //Draw a bar on top of the character.
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_mx_x,a_mx_y,a_mx_z,xbar,ybar,0);
432       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);
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()?true:false);
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.m_char,hershey_font,scale,hc.m_bar,aX,aY,a_segs,a_fill_segs) + HEIGHT * 0.01F;
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_scale,number,max_point,xp,yp,width);
510     } else if (a_font==sg::special) {
511       hershey::special_char_points(a_char,a_scale,number,max_point,xp,yp,width);
512     } else {
513       hershey::latin_char_points(a_char,a_scale,number,max_point,xp,yp,width);
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 character.
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& a_s,sencoded& a_sed){
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_cr = true;
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 1992), page 178, 180.
585   ///////////////////////////////////////////////////////////////////////////
586   static void decode_PAW(const std::string& a_s,sencoded& a_sed){
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_cr = true;
644   }
645 
646 protected:
647   std::vector<float> m_segs; //list of [begin,end]
648   size_t m_gsto_sz;
649 };
650 
651 }}
652 
653 #endif