g4tools  5.4.0
text_freetype
Go to the documentation of this file.
1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
2 // See the file tools.license for terms.
3 
4 #ifndef tools_sg_text_freetype
5 #define tools_sg_text_freetype
6 
7 //#define TOOLS_DONE_FACE
8 
9 #include <tools/sg/base_freetype>
10 #include <tools/sg/render_action>
11 #include <tools/sg/pick_action>
12 #include <tools/sg/bbox_action>
13 #include <tools/sg/enums>
14 #include <tools/lina/vec3d>
15 #include <tools/fmanip>
16 #include <tools/nostream>
17 #include <tools/lina/box_3f>
18 
19 // font_pixmap :
20 #include <tools/sg/group>
21 #include <tools/sg/blend>
23 #include <tools/platform> //for APPLE TargetConditionals.h
24 
25 #include "../glutess/glutess"
26 
27 #include <map> //for errors
28 
29 #ifndef SWIG
30 #ifndef TOOLS_USE_OUREX_FREETYPE
31 #include <ft2build.h>
32 #else
33 #include <ourex_ft2build.h>
34 
35 /*
36 #ifdef TOOLS_MEM
37 // the below coworks with raising cpp TOOLS_MEM in
38 // ourex/freetype/src/builds/unix/ftsystem.c
39 #include <tools/mem>
40 extern "C" {
41  typedef void* __FT_Memory;
42  void* ft_alloc(__FT_Memory,long size){
43  tools::mem::increment(tools::s_malloc().c_str());
44  return ::malloc(size);
45  }
46  void* ft_realloc(__FT_Memory,long,long new_size,void* block){
47  if(block==NULL) tools::mem::increment(tools::s_malloc().c_str());
48  return ::realloc(block,new_size);
49  }
50  void ft_free(__FT_Memory,void* block){
51  if(block!=NULL) tools::mem::decrement(tools::s_malloc().c_str());
52  ::free(block);
53  }
54 }
55 #endif
56 */
57 
58 #endif
59 #include FT_FREETYPE_H
60 #include FT_GLYPH_H
61 #include FT_OUTLINE_H
62 #endif
63 
64 //#define TOOLS_SG_TEXT_FREETYPE_DEBUG
65 
66 namespace tools {
67 namespace sg {
68 
71 protected:
72  text_freetype& self() const {return const_cast<text_freetype&>(*this);}
73 protected:
74  TOOLS_CLASS_STRING(TOOLS_FONT_PATH)
75 protected:
76  enum wndg_type {
80  };
81 protected: //gstos
82  virtual unsigned int create_gsto(std::ostream& a_out,tools::sg::render_manager& a_mgr) {
83  std::vector<float> gsto_data;
84 
86  const line_t& item = *it;
87  size_t pos = item.first;
88  size_t num = item.second;
89 
90  if(num<2) {
91  a_out << "tools::sg::text_freetype::create_gsto :"
92  << " strange line with " << num << " points."
93  << std::endl;
94  continue; //do we have the case num = 1 ?
95  }
96 
97  const float* data = tools::vec_data<float>(m_xys)+pos;
98 
99  // data is a line_strip(), convert it to lines.
100 
101  size_t nsegs = num-1;
102 
103  size_t ngsto = nsegs*2*3; //3 = have a z (Windows GL).
104  size_t sz = gsto_data.size();
105  gsto_data.resize(sz+ngsto);
106  float* pxyz = tools::vec_data<float>(gsto_data)+sz;
107 
109  }}
110 
111  m_gsto_lines_sz = gsto_data.size();
112 
114  const std::pair<GLUenum,triangle_t>& item = *it;
115  size_t pos = item.second.first;
116  size_t num = item.second.second;
117 
118  if(num<3) {
119  a_out << "tools::sg::text_freetype::create_gsto :"
120  << " strange triangle primitive with " << num << " points."
121  << " Primitive kind is " << (*it).first << "."
122  << std::endl;
123  continue;
124  }
125 
126  const float* data = tools::vec_data<float>(m_xys)+pos;
127 
128  if((*it).first==tools::gl::triangles()) {
129 
130  size_t ntri = num/3;
131 
132  size_t ngsto = ntri*3*3;
133  size_t sz = gsto_data.size();
134  gsto_data.resize(sz+ngsto);
135  float* pxyz = tools::vec_data<float>(gsto_data)+sz;
136 
137  tools::gl::cvt_2to3(num,data,pxyz);
138 
139  } else if((*it).first==tools::gl::triangle_fan()) {
140 
141  size_t ntri = num-2;
142 
143  size_t ngsto = ntri*3*3;
144  size_t sz = gsto_data.size();
145  gsto_data.resize(sz+ngsto);
146  float* pxyz = tools::vec_data<float>(gsto_data)+sz;
147 
149 
150  } else if((*it).first==tools::gl::triangle_strip()) {
151 
152  size_t ntri = num-2;
153 
154  size_t ngsto = ntri*3*3;
155  size_t sz = gsto_data.size();
156  gsto_data.resize(sz+ngsto);
157  float* pxyz = tools::vec_data<float>(gsto_data)+sz;
158 
160 
161  } else {
162  a_out << "tools::sg::text_freetype::create_gsto :"
163  << " unknown triangle primitive kind " << (*it).first << "."
164  << std::endl;
165  }
166 
167  }}
168 
169  m_gsto_sz = gsto_data.size();
170 
171  if(gsto_data.empty()) {
172  //a_out << "tools::sg::text_freetype::create_gsto :"
173  // << " empty buffer."
174  // << std::endl;
175  return 0;
176  }
177 
178  return a_mgr.create_gsto_from_data(gsto_data);
179  }
180 
181 public:
182  virtual void render(tools::sg::render_action& a_action) {
183  {bool _color_touched = color_touched(a_action.state());
184  bool _char_height_touched = char_height_touched(a_action.state());
185  if(touched()||_color_touched||_char_height_touched) {
186  update_sg(a_action.out(),font.touched());
187  reset_touched();
188  }}
189 
190  const tools::sg::state& state = a_action.state();
191 
193  else if(m_wndg==wndg_cw) a_action.set_winding(tools::sg::winding_cw);
194 
195  if(state.m_use_gsto) {
196  unsigned int _id = get_gsto_id(a_action.out(),a_action.render_manager());
197  if(_id) {
198  a_action.begin_gsto(_id);
199  size_t sz_tris = m_gsto_sz-m_gsto_lines_sz;
200  if(m_gsto_lines_sz) {
201  a_action.set_line_smooth(true);
203  a_action.set_polygon_offset(true);
204  }
205  if(m_gsto_lines_sz && sz_tris) {
208  }
209  tools::sg::bufpos pos = m_gsto_lines_sz*sizeof(float);
210  a_action.draw_gsto_v(tools::gl::triangles(),sz_tris/3,pos);
211  a_action.end_gsto();
212 
215  a_action.set_winding(state.m_winding);
216  return;
217  } else {
218  // use immediate rendering.
219  }
220  } else {
221  clean_gstos(&a_action.render_manager());
222  }
223 
224  // immediate rendering :
225 
229 
230  a_action.set_line_smooth(true);
231 
233  const line_t& item = *it;
234  size_t pos = item.first;
235  size_t num = item.second;
236  if(!num) continue;
237  //a_out << "tools::sg::text_freetype::render :"
238  // << " num points " << num
239  // << std::endl;
240 
241  const float* data = tools::vec_data<float>(m_xys)+pos;
242 
243  a_action.draw_vertex_array_xy(tools::gl::line_strip(),num*2,data);
244  }}
245 
246  if(m_lines.size()) a_action.set_polygon_offset(true);
247 
252  const std::pair<GLUenum,triangle_t>& item = *it;
253  size_t pos = item.second.first;
254  size_t num = item.second.second;
255  if(!num) continue;
256  //a_out << "tools::sg::text_freetype::render :"
257  // << " num points " << num
258  // << std::endl;
259 
260  const float* data = tools::vec_data<float>(m_xys)+pos;
261 
262  a_action.draw_vertex_array_xy((*it).first,num*2,data);
263  }}
264 
267  a_action.set_winding(state.m_winding);
268 
272 #if defined(ANDROID) /*|| TARGET_OS_IPHONE*/
273  // we do not have transparent texture here (see also gl/tex_img() that does img/4-bytes => img/3-bytes) :
274  {tools::sg::state& _state = a_action.state();
275  tools::colorf old_color = _state.m_color;
276  _state.m_color = tools::colorf_white();
277  a_action.color4f(_state.m_color);
278  m_bitmaps.render(a_action);
279  _state.m_color = old_color;
280  a_action.color4f(_state.m_color);}
281 #else
282  m_bitmaps.render(a_action);
283 #endif
284  }
285 
286  virtual void pick(tools::sg::pick_action& a_action) {
287  {bool _char_height_touched = char_height_touched(a_action.state());
288  if(touched()||_char_height_touched) {
289  update_sg(a_action.out(),font.touched());
290  reset_touched();
291  }}
292 
293 /*
294  //OPTIMIZATION : pick on the bounding box ?
295  if(m_face) {
296  tools::box3f box;
297  get_bounds(m_face,height,strings.values(),box);
298 
299  vec3f mn = box.mn();
300  vec3f mx = box.mx();
301 
302  mn = mtx*mn;
303  mx = mtx*mx;
304 
305  if(a_action.is_inside(b[0],b[1])) {
306  //we have a pick.
307  a_action.set_done(true);
308  a_action.set_node(this);
309  return;
310  }
311 
312  if(a_action.intersect(p1[0],p1[1],p2[0],p2[1],p3[0],p3[1])) {
313  a_action.set_done(true);
314  a_action.set_node(this);
315  return;
316  }
317  }
318  return;
319 */
320 
324 
326  const line_t& item = *it;
327  size_t pos = item.first;
328  size_t num = item.second;
329  const float* data = tools::vec_data<float>(m_xys)+pos;
330  if(a_action.add__line_strip_xy(*this,2*num,data,true)) return;
331  }}
332 
333 
338  const std::pair<GLUenum,triangle_t>& item = *it;
339  size_t pos = item.second.first;
340  size_t num = item.second.second;
341  const float* data = tools::vec_data<float>(m_xys)+pos;
342  if(a_action.add__primitive_xy(*this,item.first,2*num,data,true)) return;
343  }}
344 
348  m_bitmaps.pick(a_action);
349  }
350 
351  virtual void bbox(tools::sg::bbox_action& a_action) {
352  {bool _char_height_touched = char_height_touched(a_action.state());
353  if(touched()||_char_height_touched) {
354  update_sg(a_action.out(),font.touched());
355  reset_touched();
356  }}
357 
359  const line_t& item = *it;
360  size_t num = item.second;
361  const float* data = tools::vec_data<float>(m_xys)+item.first;
362 
363  float px,py,pz;
364  float* pos = (float*)data;
365  for(size_t index=0;index<num;index++) {
366  px = *pos;pos++;
367  py = *pos;pos++;
368  pz = 0;
369  a_action.add_one_point(px,py,pz);
370  }
371 
372  }}
373 
378  const std::pair<GLUenum,triangle_t>& item = *it;
379  size_t num = item.second.second;
380  const float* data = tools::vec_data<float>(m_xys)+item.second.first;
381 
382  float px,py,pz;
383  float* pos = (float*)data;
384  for(size_t index=0;index<num;index++) {
385  px = *pos;pos++;
386  py = *pos;pos++;
387  pz = 0;
388  a_action.add_one_point(px,py,pz);
389  }
390  }}
391 
395  m_bitmaps.bbox(a_action);
396  }
397 
398 public:
400  :parent()
401 
402  ,m_library(0)
403  ,m_face(0)
405  ,m_verbose(false)
406  ,m_scale(1)
407  ,m_pos(0)
408  ,m_char_height(0)
409  {
410  if(!initialize()){} //throw
411  }
412  virtual ~text_freetype(){
413  if(m_face) ::FT_Done_Face(m_face);
414  if(m_library) ::FT_Done_FreeType(m_library);
415  clear_trids();
416  }
417 public:
419  :parent(a_from)
420 
421  ,m_library(0)
422  ,m_face(0)
424  ,m_verbose(a_from.m_verbose)
425  ,m_scale(1)
426  ,m_pos(0)
427  ,m_char_height(0)
428  {
429  if(!initialize()){} //throw
430  }
431 
433  parent::operator=(a_from);
434  if(&a_from==this) return *this;
435 
436  if(m_face) {::FT_Done_Face(m_face);m_face = 0;}
437  if(m_library) {::FT_Done_FreeType(m_library);m_library = 0;}
438  clear_trids();
439 
440  m_encoding_offset = 0;
441  m_verbose = a_from.m_verbose;
442  m_scale = 1;
443  m_char_height = 0;
444 
445  if(!initialize()){} //throw
446 
447  return *this;
448  }
449 public: //tools::sg::base_text :
450  virtual float ascent(float a_height) const {
451  tools::nostream out;
452  if(!m_face) self().load_face(out);
453  if(!m_face) return 0;
454  float value;
455  if(!ascent(out,self().m_face,a_height,value)) return 0;
456 #ifdef TOOLS_DONE_FACE
457  ::FT_Done_Face(m_face);
458  self().m_face = 0;
459 #endif
460  return value;
461  }
462 
463  virtual float descent(float a_height) const {
464  tools::nostream out;
465  if(!m_face) self().load_face(out);
466  if(!m_face) return 0;
467  float value;
468  if(!descent(out,self().m_face,a_height,value)) return 0;
469 #ifdef TOOLS_DONE_FACE
470  ::FT_Done_Face(m_face);
471  self().m_face = 0;
472 #endif
473  return value;
474  }
475 
476  virtual float y_advance(float a_height) const {
477  tools::nostream out;
478  if(!m_face) self().load_face(out);
479  if(!m_face) return 0;
480  float value;
481  if(!y_advance(out,self().m_face,a_height,value)) return 0;
482 #ifdef TOOLS_DONE_FACE
483  ::FT_Done_Face(m_face);
484  self().m_face = 0;
485 #endif
486  return value;
487  }
488 
489  virtual void get_bounds(float a_height,
490  float& a_mn_x,float& a_mn_y,float& a_mn_z,
491  float& a_mx_x,float& a_mx_y,float& a_mx_z) const {
492  tools::nostream out;
493  if(!m_face) self().load_face(out);
494  if(!m_face) return;
495  if(strings.values().size()) {
496  if(!get_bounds(out,self().m_face,a_height,strings.values(),a_mn_x,a_mn_y,a_mn_z,a_mx_x,a_mx_y,a_mx_z)) return;
497  } else if(unitext.values().size()) {
498  if(!get_bounds(out,self().m_face,a_height,unitext.values(),a_mn_x,a_mn_y,a_mn_z,a_mx_x,a_mx_y,a_mx_z)) return;
499  }
500 #ifdef TOOLS_DONE_FACE
501  ::FT_Done_Face(m_face);
502  self().m_face = 0;
503 #endif
504  }
505 
506  virtual bool truncate(const std::string& a_string,float a_height,float a_cut_width,std::string& a_out) const {
507  a_out.clear();
508  tools::nostream out;
509  if(!m_face) self().load_face(out);
510  if(!m_face) return false;
511  if(!truncate(out,self().m_face,a_height,a_string,a_cut_width,a_out)) return false;
512 #ifdef TOOLS_DONE_FACE
513  ::FT_Done_Face(m_face);
514  self().m_face = 0;
515 #endif
516  return true;
517  }
518 
519  void dump_unitext(std::ostream& a_out) {
520  //unitext.values().size()
521  a_out << "unitext size : " << unitext.values().size() << std::endl;
523  const uniline& line = *vit;
524  a_out << "beg line :" << std::endl;
525  //a_out << line << std::endl;
527  a_out << ((unsigned int)*it) << std::endl;
528  }
529  a_out << "end line." << std::endl;
530  }
531  }
532 
533 protected:
534  bool initialize() { //called from constructors.
535  FT_Error error = ::FT_Init_FreeType(&m_library);
536  if(error) {
537  //m_out << "tools::sg::text_freetype :"
538  // << " error : " << serror(error) << "."
539  // << std::endl;
540  m_library = 0;
541  return false;
542  }
543  // cast because of const/not const according freetype version.
544  // (Recent version have "const FT_Vector*" in args).
545  m_funcs.move_to = (FT_Outline_MoveToFunc)outline_move_to;
546  m_funcs.line_to = (FT_Outline_LineToFunc)outline_line_to;
547  m_funcs.conic_to = (FT_Outline_ConicToFunc)outline_conic_to;
548  m_funcs.cubic_to = (FT_Outline_CubicToFunc)outline_cubic_to;
549  m_funcs.shift = 0;
550  m_funcs.delta = 0;
551 
552  // Comment from OGLFT :
553  // Default number of steps to break TrueType and Type1 arcs into.
554  // (Note: this looks good to me, anyway)
555  m_steps = 4;
556  m_delta = 1.0f /(float)m_steps;
559 
560  return true;
561  }
562 
566  enum update_what {
567  faces = 0,
568  lines = 1,
570  };
571 
572  bool color_touched(const tools::sg::state& a_state) {
573  if(modeling!=tools::sg::font_pixmap) return false;
574  if(a_state.m_color==m_front_color) return false;
575  m_front_color = a_state.m_color;
576  return true;
577  }
578 
579  bool char_height_touched(const tools::sg::state& a_state) {
580  if(modeling!=tools::sg::font_pixmap) return false;
581 
582  float ymn,ymx;
583  {float x,y,z,w;
584  x = 0;y = -height.value()*0.5f;z = 0;
585  if(!a_state.project_point(x,y,z,w)) return false;
586  ymn = y;
587  x = 0;y = height.value()*0.5f;z = 0;
588  if(!a_state.project_point(x,y,z,w)) return false;
589  ymx = y;}
590  float screen_height = ymx-ymn;
591  if(a_state.m_wh) screen_height *= a_state.m_wh; else screen_height = 100;
592 
593  //::printf("debug : char_height_touched %g\n",screen_height);
594 
595  if(screen_height==m_char_height) return false;
596  m_char_height = screen_height;
597  return true;
598  }
599 
600  void update_sg(std::ostream& a_out,bool a_load_font) {
601  if(a_load_font) load_face(a_out);
602 
603  clean_gstos(); //must reset for all render_manager.
604 
605  if(!m_face) return;
606 
607  //a_out << "tools::sg::text_freetype::update_sg :"
608  // << " font file opened."
609  // << std::endl;
610 
611  m_encoding_offset = 0;
613  a_out << "tools::sg::text_freetype::update_sg :"
614  << " encoding_offset failed."
615  << std::endl;
616  ::FT_Done_Face(m_face);
617  m_face = 0;
618  return;
619  }
620 
621  m_xys.clear();
622  m_pos = 0;
623  m_lines.clear();
624  m_triangles.clear();
625  m_bitmaps.clear();
626  m_tqs.clear();
627 
629 
631  if(m_char_height<=0) return;
633  blend->on = true; //to handle background transparency.
635  if(!bitmap_2_gl(a_out)) {m_bitmaps.clear();m_tqs.clear();return;}
636  } else {
637  update_what _what = lines;
638  //if(modeling==tools::sg::font_filled) _what = faces_and_lines;
640  if((_what==faces)||(_what==faces_and_lines)) outline_triangles_2_gl(a_out);
641  if((_what==lines)||(_what==faces_and_lines)) outline_lines_2_gl(a_out);
642  }
643 
644  if(vjust==tools::sg::bottom) {
645  } else if(vjust==tools::sg::middle) {
646  float mn_x,mn_y,mn_z;
647  float mx_x,mx_y,mx_z;
648  get_bounds(height,mn_x,mn_y,mn_z,mx_x,mx_y,mx_z);
649  float szy = mx_y - mn_y;
650 
652  line_t& item = *it;
653  size_t pos = item.first;
654  size_t npt = item.second;
655  float* data = tools::vec_data<float>(m_xys)+pos+1;
656  for(size_t i=0;i<npt;i++,data+=2) *data -= 0.5F * szy;
657  }}
658 
660  std::pair<GLUenum,triangle_t>& item = *it;
661  size_t pos = item.second.first;
662  size_t npt = item.second.second;
663  float* data = tools::vec_data<float>(m_xys)+pos+1;
664  for(size_t i=0;i<npt;i++,data+=2) *data -= 0.5F * szy;
665  }}
666 
668  std::vector<tools::vec3f>& vcs = (*itqs)->corners.values();
669  for(size_t i=0;i<4;i++) vcs[i][1] -= 0.5f * szy;
670  }}
671 
672  } else if(vjust==tools::sg::top) {
673  float mn_x,mn_y,mn_z;
674  float mx_x,mx_y,mx_z;
675  get_bounds(height,mn_x,mn_y,mn_z,mx_x,mx_y,mx_z);
676  float szy = mx_y - mn_y;
677 
679  line_t& item = *it;
680  size_t pos = item.first;
681  size_t npt = item.second;
682  float* data = tools::vec_data<float>(m_xys)+pos+1;
683  for(size_t i=0;i<npt;i++,data+=2) *data -= szy;
684  }}
685 
687  std::pair<GLUenum,triangle_t>& item = *it;
688  size_t pos = item.second.first;
689  size_t npt = item.second.second;
690  float* data = tools::vec_data<float>(m_xys)+pos+1;
691  for(size_t i=0;i<npt;i++,data+=2) *data -= szy;
692  }}
693 
695  std::vector<tools::vec3f>& vcs = (*itqs)->corners.values();
696  for(size_t i=0;i<4;i++) vcs[i][1] -= szy;
697  }}
698 
699  }
700 
701  m_tqs.clear();
702 
703 #ifdef TOOLS_DONE_FACE
704  ::FT_Done_Face(m_face);
705  m_face = 0;
706 #endif
707  }
708 
709  void outline_lines_2_gl(std::ostream& a_out) {
710  if(!set_char_size(a_out,m_face,height.value(),m_scale)) return;
711  FT_Pos face_height = m_face->size->metrics.height; //FT_Pos (long)
712 
713  m_tobj = 0; //IMPORTANT.
714 
715  if(strings.values().size()) {
716  float yline = 0;
717  tools_vforcit(std::string,strings.values(),vit) {
718  const std::string& line = *vit;
719  //a_out << line << std::endl;
720  m_trans_x = 0;
721  m_trans_y = yline;
722  size_t ibeg = m_lines.size(); //for hjust.
723  tools_sforcit(line,it) {
724  if(!char_outline_2_gl(a_out,*it + m_encoding_offset)) return;
725  }
726  yline += -float(face_height)*m_scale; //height >0
727 
728  {float sx = m_trans_x;
729  if(hjust==tools::sg::center) {
730  size_t num = m_lines.size();
731  for(size_t index=ibeg;index<num;index++) {
732  line_t& item = m_lines[index];
733  size_t pos = item.first;
734  size_t npt = item.second;
735  float* data = tools::vec_data<float>(m_xys)+pos;
736  for(size_t i=0;i<npt;i++,data+=2) *data -= 0.5F * sx;
737  }
738  } else if(hjust==tools::sg::right) {
739  size_t num = m_lines.size();
740  for(size_t index=ibeg;index<num;index++) {
741  line_t& item = m_lines[index];
742  size_t pos = item.first;
743  size_t npt = item.second;
744  float* data = tools::vec_data<float>(m_xys)+pos;
745  for(size_t i=0;i<npt;i++,data+=2) *data -= sx;
746  }
747  }}
748  }
749 
750  } else if(unitext.values().size()) {
751  float yline = 0;
753  const uniline& line = *vit;
754  //a_out << line << std::endl;
755  m_trans_x = 0;
756  m_trans_y = yline;
757  size_t ibeg = m_lines.size(); //for hjust.
759  if(!char_outline_2_gl(a_out,*it)) return;
760  }
761  yline += -float(face_height)*m_scale; //height>0
762 
763  {float sx = m_trans_x;
764  if(hjust==tools::sg::center) {
765  size_t num = m_lines.size();
766  for(size_t index=ibeg;index<num;index++) {
767  line_t& item = m_lines[index];
768  size_t pos = item.first;
769  size_t npt = item.second;
770  float* data = tools::vec_data<float>(m_xys)+pos;
771  for(size_t i=0;i<npt;i++,data+=2) *data -= 0.5F*sx;
772  }
773  } else if(hjust==tools::sg::center) {
774  size_t num = m_lines.size();
775  for(size_t index=ibeg;index<num;index++) {
776  line_t& item = m_lines[index];
777  size_t pos = item.first;
778  size_t npt = item.second;
779  float* data = tools::vec_data<float>(m_xys)+pos;
780  for(size_t i=0;i<npt;i++,data+=2) *data -= sx;
781  }
782  }}
783  }
784  }
785  }
786 
787  bool char_outline_2_gl(std::ostream& a_out,unsigned int a_unichar) {
788  FT_ULong charcode = a_unichar; //charcode is UTF-32.
789  FT_UInt glyph_index = ::FT_Get_Char_Index(m_face,charcode);
790  //NOTE : if not found -> glyph_index = 0 which is the "missing glyph".
791  if((FT_Long)glyph_index>=m_face->num_glyphs) {
792  a_out << "tools::sg::text_freetype::char_outline_2_gl :"
793  << " FT_Get_Char_Index : failed for char : " << a_unichar
794  << std::endl;
795  ::FT_Done_Face(m_face);
796  m_face = 0;
797  return false;
798  }
799 
800  {FT_Error error = ::FT_Load_Glyph(m_face,glyph_index,load_flags());
801  if(error) {
802  a_out << "tools::sg::text_freetype::char_outline_2_gl :"
803  << " for character " << a_unichar
804  << ",FT_Load_Glyph : error : " << serror(error)
805  << std::endl;
806  ::FT_Done_Face(m_face);
807  m_face = 0;
808  return false;
809  }}
810 
811  //FT_GlyphSlot FT_Face.glyph;
812  if(m_face->glyph->format!=FT_GLYPH_FORMAT_OUTLINE) {
813  a_out << "tools::sg::text_freetype::char_outline_2_gl :"
814  << " for font " << tools::sout(font.value())
815  << " and for character " << a_unichar
816  << " glyph not at format outline."
817  << std::endl;
818  ::FT_Done_Face(m_face);
819  m_face = 0;
820  return false;
821  }
822 
823  FT_Outline outline = m_face->glyph->outline;
824 
825  {FT_Error error = ::FT_Outline_Decompose(&outline,&m_funcs,this);
826  if(error) {
827  a_out << "tools::sg::text_freetype::char_outline_2_gl :"
828  << " for character " << a_unichar
829  << ",FT_Outline_Decompose : error : " << serror(error)
830  << std::endl;
831  ::FT_Done_Face(m_face);
832  m_face = 0;
833  return false;
834  }}
835 
836  flush_line();
837 
838  m_trans_x += float(m_face->glyph->advance.x)*m_scale;
839  m_trans_y += float(m_face->glyph->advance.y)*m_scale;
840 
841  {wndg_type wdg = ((outline.flags & FT_OUTLINE_REVERSE_FILL)?wndg_ccw:wndg_cw);
842  if(m_wndg==wndg_not_done) {
843  m_wndg = wdg;
844  } else if(m_wndg!=wdg) {
845  a_out << "tools::sg::text_freetype::char_outline_2_gl :"
846  << " for character " << a_unichar << ", winding anomaly."
847  << std::endl;
848  }}
849 
850  return true;
851  }
852 
853 protected:
854  void flush_line(){
855  size_t num = (m_xys.size()-m_pos)/2;
856  if(num) {
857  m_lines.push_back(line_t(m_pos,num));
858  }
859  m_pos = m_xys.size();
860  }
861 
865  void outline_triangles_2_gl(std::ostream& a_out) {
866  if(!set_char_size(a_out,m_face,height.value(),m_scale)) return;
867  FT_Pos face_height = m_face->size->metrics.height; //FT_Pos (long)
868 
869  m_tobj = gluNewTess();
870 
871 #ifdef TOOLS_USE_NATIVE_GLUTESS
877 #else
878  // NOTE : the gluTessCallback_<enum>() functions are inlib/glutess specific.
879  // They had been introduced to avoid g++-8.1.0 warnings :
880  // warnings : cast between incompatible function types.
886 #endif
887 
889 
890  //::gluTessProperty(m_tobj, GLU_TESS_TOLERANCE, 0);
891  //::gluTessNormal(m_tobj, 0.0f, 0.0f, -1.0f);
892 
893  if(strings.values().size()) {
894  float yline = 0;
895  tools_vforcit(std::string,strings.values(),vit) {
896  const std::string& line = *vit;
897  //a_out << line << std::endl;
898  m_trans_x = 0;
899  m_trans_y = yline;
900  size_t ibeg = m_triangles.size(); //for hjust.
901  tools_sforcit(line,it) {
902  if(!char_triangles_2_gl(a_out,*it + m_encoding_offset)) {
904  m_tobj = 0;
905  return;
906  }
907  }
908  yline += -float(face_height)*m_scale; //height>0
909 
910  {float sx = m_trans_x;
911  if(hjust==tools::sg::center) {
912  size_t num = m_triangles.size();
913  for(size_t index=ibeg;index<num;index++) {
914  std::pair<GLUenum,triangle_t>& item = m_triangles[index];
915  size_t pos = item.second.first;
916  size_t npt = item.second.second;
917  float* data = tools::vec_data<float>(m_xys)+pos;
918  for(size_t i=0;i<npt;i++,data+=2) *data -= sx*0.5f;
919  }
920  } else if(hjust==tools::sg::right) {
921  size_t num = m_triangles.size();
922  for(size_t index=ibeg;index<num;index++) {
923  std::pair<GLUenum,triangle_t>& item = m_triangles[index];
924  size_t pos = item.second.first;
925  size_t npt = item.second.second;
926  float* data = tools::vec_data<float>(m_xys)+pos;
927  for(size_t i=0;i<npt;i++,data+=2) *data -= sx;
928  }
929  }}
930  }
931  } else if(unitext.values().size()) {
932  float yline = 0;
934  const uniline& line = *vit;
935  //a_out << line << std::endl;
936  m_trans_x = 0;
937  m_trans_y = yline;
938  size_t ibeg = m_triangles.size(); //for hjust.
940  if(!char_triangles_2_gl(a_out,*it)) {
942  m_tobj = 0;
943  return;
944  }
945  }
946  yline += -float(face_height)*m_scale; //height>0
947 
948  {float sx = m_trans_x;
949  if(hjust==tools::sg::center) {
950  size_t num = m_triangles.size();
951  for(size_t index=ibeg;index<num;index++) {
952  std::pair<GLUenum,triangle_t>& item = m_triangles[index];
953  size_t pos = item.second.first;
954  size_t npt = item.second.second;
955  float* data = tools::vec_data<float>(m_xys)+pos;
956  for(size_t i=0;i<npt;i++,data+=2) *data -= sx*0.5f;
957  }
958  } else if(hjust==tools::sg::right) {
959  size_t num = m_triangles.size();
960  for(size_t index=ibeg;index<num;index++) {
961  std::pair<GLUenum,triangle_t>& item = m_triangles[index];
962  size_t pos = item.second.first;
963  size_t npt = item.second.second;
964  float* data = tools::vec_data<float>(m_xys)+pos;
965  for(size_t i=0;i<npt;i++,data+=2) *data -= sx;
966  }
967  }}
968  }
969  }
970 
972  m_tobj = 0;
973  }
974 
975  bool char_triangles_2_gl(std::ostream& a_out,unsigned int a_unichar) {
976  //if(m_verbose) {
977  // a_out << "tools::sg::text_freetype::char_triangles_2_gl :"
978  // << " do " << a_unichar << "."
979  // << std::endl;
980  //}
981 
982  FT_ULong charcode = a_unichar; //charcode is UTF-32.
983  FT_UInt glyph_index = ::FT_Get_Char_Index(m_face,charcode);
984  //NOTE : if not found -> glyph_index = 0 which is the "missing glyph".
985  if((FT_Long)glyph_index>=m_face->num_glyphs) {
986  a_out << "tools::sg::text_freetype::char_triangles_2_gl :"
987  << " FT_Get_Char_Index : failed for char : " << a_unichar
988  << std::endl;
989  ::FT_Done_Face(m_face);
990  m_face = 0;
991  return false;
992  }
993 
994  {FT_Error error = ::FT_Load_Glyph(m_face,glyph_index,load_flags());
995  if(error) {
996  a_out << "tools::sg::text_freetype::char_triangles_2_gl :"
997  << " for character " << a_unichar
998  << ",FT_Load_Glyph : error : " << serror(error)
999  << std::endl;
1000  ::FT_Done_Face(m_face);
1001  m_face = 0;
1002  return false;
1003  }}
1004 
1005  //FT_GlyphSlot FT_Face.glyph;
1006  if(m_face->glyph->format!=FT_GLYPH_FORMAT_OUTLINE) {
1007  a_out << "tools::sg::text_freetype::char_triangles_2_gl :"
1008  << " for font " << tools::sout(font.value())
1009  << " and for character " << a_unichar
1010  << " glyph not at format outline."
1011  << std::endl;
1012  ::FT_Done_Face(m_face);
1013  m_face = 0;
1014  return false;
1015  }
1016 
1017  FT_Outline outline = m_face->glyph->outline;
1018 
1019  m_glutess_trids_num = 0;
1020  m_combine_trids_num = 0;
1021 
1022  m_contour_open = false;
1023 
1025 
1026  {FT_Error error = ::FT_Outline_Decompose(&outline,&m_funcs,this);
1027  if(error) {
1028  a_out << "tools::sg::text_freetype::char_triangles_2_gl :"
1029  << " for character " << a_unichar
1030  << ",FT_Outline_Decompose : error : " << serror(error)
1031  << std::endl;
1032  ::FT_Done_Face(m_face);
1033  m_face = 0;
1034  return false;
1035  }}
1036 
1037  if(m_contour_open) {
1039  m_contour_open = false;
1040  }
1041 
1042  ::gluTessEndPolygon(m_tobj); //triggers callbacks and fill m_triangles.
1043 
1044  m_trans_x += float(m_face->glyph->advance.x)*m_scale;
1045  m_trans_y += float(m_face->glyph->advance.y)*m_scale;
1046 
1047  {wndg_type wdg = ((outline.flags & FT_OUTLINE_REVERSE_FILL)?wndg_ccw:wndg_cw);
1048  if(m_wndg==wndg_not_done) {
1049  m_wndg = wdg;
1050  } else if(m_wndg!=wdg) {
1051  a_out << "tools::sg::text_freetype::char_triangles_2_gl :"
1052  << " for character " << a_unichar << ", winding anomaly."
1053  << std::endl;
1054  }}
1055 
1056  return true;
1057  }
1058 
1062  bool bitmap_2_gl(std::ostream& a_out) {
1063  //if(!set_char_size(a_out,m_face,height.value(),m_scale)) return;
1064  //::printf("debug : xxxxx %g\n",m_char_height);
1065  FT_F26Dot6 wchar = (FT_F26Dot6)(m_char_height*64);
1066  FT_F26Dot6 hchar = (FT_F26Dot6)(m_char_height*64);
1067  FT_UInt hres = 72;
1068  FT_UInt vres = 72;
1069  FT_Error error = ::FT_Set_Char_Size(m_face,wchar,hchar,hres,vres);
1070  if(error) {
1071  a_out << "tools::sg::text_freetype::bitmap_2_gl :"
1072  << " FT_Set_Char_Size : error : " << serror(error) << "."
1073  << std::endl;
1074  ::FT_Done_Face(m_face);
1075  m_face = 0;
1076  return false;
1077  }
1078  m_scale = height.value()/float(hchar);
1079 
1080  FT_Pos face_height = m_face->size->metrics.height; //FT_Pos (long)
1081  //::printf("debug : face_height %lu\n",face_height);
1082  if(strings.values().size()) {
1083  float yline = 0;
1084  tools_vforcit(std::string,strings.values(),vit) {
1085  const std::string& line = *vit;
1086  //a_out << line << std::endl;
1087  m_trans_x = 0;
1088  m_trans_y = yline;
1089  size_t ibeg = m_tqs.size(); //for hjust.
1090  tools_sforcit(line,it) {
1091  if(!char_2_bitmap(a_out,*it + m_encoding_offset)) return false;
1092  }
1093  yline += -float(face_height)*m_scale; //height>0
1094 
1095  {float sx = m_trans_x;
1096  if(hjust==tools::sg::center) {
1097  size_t num = m_tqs.size();
1098  for(size_t index=ibeg;index<num;index++) {
1099  std::vector<tools::vec3f>& vcs = m_tqs[index]->corners.values();
1100  for(size_t i=0;i<4;i++) vcs[i][0] -= sx*0.5f;
1101  }
1102  } else if(hjust==tools::sg::right) {
1103  size_t num = m_tqs.size();
1104  for(size_t index=ibeg;index<num;index++) {
1105  std::vector<tools::vec3f>& vcs = m_tqs[index]->corners.values();
1106  for(size_t i=0;i<4;i++) vcs[i][0] -= sx;
1107  }
1108  }}
1109  }
1110  } else if(unitext.values().size()) {
1111  float yline = 0;
1113  const uniline& line = *vit;
1114  //a_out << line << std::endl;
1115  m_trans_x = 0;
1116  m_trans_y = yline;
1117  size_t ibeg = m_tqs.size(); //for hjust.
1118  tools_vforcit(unichar,line,it) {
1119  if(!char_2_bitmap(a_out,*it)) return false;
1120  }
1121  yline += -float(face_height)*m_scale; //height>0
1122 
1123  {float sx = m_trans_x;
1124  if(hjust==tools::sg::center) {
1125  size_t num = m_tqs.size();
1126  for(size_t index=ibeg;index<num;index++) {
1127  std::vector<tools::vec3f>& vcs = m_tqs[index]->corners.values();
1128  for(size_t i=0;i<4;i++) vcs[i][0] -= sx*0.5f;
1129  }
1130  } else if(hjust==tools::sg::right) {
1131  size_t num = m_tqs.size();
1132  for(size_t index=ibeg;index<num;index++) {
1133  std::vector<tools::vec3f>& vcs = m_tqs[index]->corners.values();
1134  for(size_t i=0;i<4;i++) vcs[i][0] -= sx;
1135  }
1136  }}
1137  }
1138  }
1139  return true;
1140  }
1141 
1142  bool char_2_bitmap(std::ostream& a_out,unsigned int a_unichar) {
1143  //if(m_verbose) {
1144  // a_out << "tools::sg::text_freetype::char_2_bitmap :"
1145  // << " do " << a_unichar << "."
1146  // << std::endl;
1147  //}
1148 
1149  FT_ULong charcode = a_unichar; //charcode is UTF-32.
1150  FT_UInt glyph_index = ::FT_Get_Char_Index(m_face,charcode);
1151  //NOTE : if not found -> glyph_index = 0 which is the "missing glyph".
1152  if((FT_Long)glyph_index>=m_face->num_glyphs) {
1153  a_out << "tools::sg::text_freetype::char_2_bitmap :"
1154  << " FT_Get_Char_Index : failed for char : " << a_unichar
1155  << std::endl;
1156  ::FT_Done_Face(m_face);
1157  m_face = 0;
1158  return false;
1159  }
1160 
1161  {FT_Error error = ::FT_Load_Glyph(m_face,glyph_index,load_flags());
1162  if(error) {
1163  a_out << "tools::sg::text_freetype::char_2_bitmap :"
1164  << " for character " << a_unichar
1165  << ",FT_Load_Glyph : error : " << serror(error)
1166  << std::endl;
1167  ::FT_Done_Face(m_face);
1168  m_face = 0;
1169  return false;
1170  }}
1171 
1172  FT_Glyph glyph;
1173  {FT_Error error = ::FT_Get_Glyph(m_face->glyph,&glyph);
1174  if (error) {
1175  a_out << "tools::sg::text_freetype::char_2_bitmap :"
1176  << " for font " << tools::sout(font.value())
1177  << " and for character " << a_unichar
1178  << " could not get glyph."
1179  << std::endl;
1180  ::FT_Done_Face(m_face);
1181  m_face = 0;
1182  return false;
1183  }}
1184 
1185  bool smoothing = true;
1186  {FT_Error error = ::FT_Glyph_To_Bitmap(&glyph,(smoothing?ft_render_mode_normal:ft_render_mode_mono),0,1);
1187  if (error) {
1188  a_out << "tools::sg::text_freetype::char_2_bitmap :"
1189  << " for font " << tools::sout(font.value())
1190  << " and for character " << a_unichar
1191  << " could not get glyph bitmap."
1192  << std::endl;
1193  ::FT_Done_Glyph(glyph);
1194  ::FT_Done_Face(m_face);
1195  m_face = 0;
1196  return false;
1197  }}
1198 
1199  //typedef struct FT_Bitmap_ {
1200  // int rows;
1201  // int width;
1202  // int pitch;
1203  // unsigned char* buffer;
1204  // short num_grays;
1205  // char pixel_mode;
1206  // char palette_mode;
1207  // void* palette;
1208  //} FT_Bitmap;
1209 
1210  FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
1211 
1212  //::printf("debug : unichar %u : r %d w %d pitch %d : grays %d\n",
1213  // a_unichar,bitmap->bitmap.rows,bitmap->bitmap.width,bitmap->bitmap.pitch,bitmap->bitmap.num_grays);
1214 
1215  if( (bitmap->bitmap.pixel_mode!=ft_pixel_mode_mono) &&
1216  (bitmap->bitmap.pixel_mode!=ft_pixel_mode_grays) ){
1217  a_out << "tools::sg::text_freetype::char_2_bitmap :"
1218  << " for font " << tools::sout(font.value())
1219  << " and for character " << a_unichar
1220  << " not a mono or grays pixmap."
1221  << std::endl;
1222  ::FT_Done_Glyph(glyph);
1223  ::FT_Done_Face(m_face);
1224  m_face = 0;
1225  return false;
1226  }
1227 
1228  if(bitmap->bitmap.pitch<0) {
1229  a_out << "tools::sg::text_freetype::char_2_bitmap :"
1230  << " for font " << tools::sout(font.value())
1231  << " and for character " << a_unichar
1232  << " negative bitmap pitch."
1233  << std::endl;
1234  ::FT_Done_Glyph(glyph);
1235  ::FT_Done_Face(m_face);
1236  m_face = 0;
1237  return false;
1238  }
1239 
1240  unsigned int img_w = 0;
1241  unsigned int img_h = 0;
1242  unsigned int img_bpp = 4;
1243  size_t img_sz = 0;
1244 
1245  if(bitmap->bitmap.pixel_mode==ft_pixel_mode_mono) {
1246  a_out << "tools::sg::text_freetype::char_2_bitmap : mode_mono : not yet handled." << std::endl;
1247 
1248  //img_grays = 1;
1249  img_h = bitmap->bitmap.rows;
1250  //WARNING : bitmap->bitmap.pitch != int((bitmap->bitmap.width+7)/8) !!!
1251  // OpenGL wants the below for cols.
1252  img_w = (bitmap->bitmap.width+7)/8;
1253  img_sz = img_w * img_h;
1254 
1255  ::FT_Done_Glyph(glyph);
1256  ::FT_Done_Face(m_face);
1257  m_face = 0;
1258  return false;
1259 
1260  } else { //ft_pixel_mode_grays
1261  if(int(bitmap->bitmap.width)!=bitmap->bitmap.pitch) {
1262  a_out << "tools::sg::text_freetype::char_2_bitmap :"
1263  << " for font " << tools::sout(font.value())
1264  << " and for character " << a_unichar
1265  << "bitmap pitch (" << bitmap->bitmap.pitch << ") != width (" << bitmap->bitmap.width << ")."
1266  << std::endl;
1267  ::FT_Done_Glyph(glyph);
1268  ::FT_Done_Face(m_face);
1269  m_face = 0;
1270  return false;
1271  }
1272  img_w = bitmap->bitmap.width;
1273  img_h = bitmap->bitmap.rows;
1274  img_sz = img_w * img_h * img_bpp;
1275  //img_grays = bitmap->bitmap.num_grays;
1276  }
1277 
1278  if(img_sz<=0) {
1279  // This may happen (for example for the space character).
1280  } else {
1281  tools::byte* img_buffer = new tools::byte[img_sz];
1282  if(!img_buffer) {
1283  a_out << "tools::sg::text_freetype::char_2_bitmap :"
1284  << " for font " << tools::sout(font.value())
1285  << " and for character " << a_unichar
1286  << ", can't alloc bitmap buffer for character."
1287  << std::endl;
1288  ::FT_Done_Glyph(glyph);
1289  ::FT_Done_Face(m_face);
1290  m_face = 0;
1291  return false;
1292  }
1293  // The bitmap is upside down for OpenGL.
1294  float a,b;
1295  tools::colorf back_color = tools::colorf_white();
1296  back_color.set_a(0); //transparent background.
1297  typedef unsigned char uchar;
1298  for(unsigned int row=0;row<img_h;++row) {
1299  unsigned char* from = (unsigned char*)bitmap->bitmap.buffer + (bitmap->bitmap.rows-row-1)*bitmap->bitmap.pitch;
1300  unsigned char* to = img_buffer + row * img_w * img_bpp;
1301  for(unsigned int col=0;col<img_w;++col,++from) {
1302  a = float(*from)/255.0f;
1303  b = float(255-*from)/255.0f;
1304  *to = uchar(m_front_color.ruchar()*a+back_color.ruchar()*b);to++;
1305  *to = uchar(m_front_color.guchar()*a+back_color.guchar()*b);to++;
1306  *to = uchar(m_front_color.buchar()*a+back_color.buchar()*b);to++;
1307  *to = uchar(m_front_color.auchar()*a+back_color.auchar()*b);to++;
1308  }
1309  }
1310 
1311  FT_BBox _bbox;
1312  FT_Glyph_Get_CBox(glyph,ft_glyph_bbox_pixels,&_bbox);
1313  //float _width = float(_bbox.xMax)-float(_bbox.xMin);
1314  //float _height = float(_bbox.yMax)-float(_bbox.yMin);
1315  //aAdvance = int(face->glyph->advance.x/64);
1316 
1317  std::vector<tools::vec3f> vcs;
1318  //::printf("debug : box : %d %d %d %d\n",_bbox.xMin,_bbox.xMax,_bbox.yMin,_bbox.yMax);
1319  float scale = height.value()/m_char_height;
1320  float x_min = float(_bbox.xMin)*scale+m_trans_x;
1321  float x_max = float(_bbox.xMax)*scale+m_trans_x;
1322  float y_min = float(_bbox.yMin)*scale+m_trans_y;
1323  float y_max = float(_bbox.yMax)*scale+m_trans_y;
1324  //::printf("debug : scale %g, trans %g %g\n",m_scale,m_trans_x,m_trans_y);
1325  //::printf("debug : corners %g %g %g %g\n",x_min,x_max,y_min,y_max);
1326 
1327  vcs.push_back(tools::vec3f(x_min,y_min,0));
1328  vcs.push_back(tools::vec3f(x_max,y_min,0));
1329  vcs.push_back(tools::vec3f(x_max,y_max,0));
1330  vcs.push_back(tools::vec3f(x_min,y_max,0));
1331 
1333  _node->img.value().set(img_w,img_h,img_bpp,img_buffer,true);
1334  _node->expand = true;
1335  _node->back_color = tools::colorf_white(); //used as back pixel when expanding.
1336  _node->back_color.value().set_a(0); //transparent background.
1337  //_node->nearest = false; //to have antialiasing on texture.
1338  _node->corners.set_values(vcs);
1339 
1340  m_bitmaps.add(_node);
1341  m_tqs.push_back(_node);
1342 
1343  /*
1344  if(bitmap->bitmap.pixel_mode==ft_pixel_mode_mono) {
1345  if((aChar=='T')||(aChar=='a')||(aChar=='o')||(aChar=='L')) {
1346  printf("bitmap for '%c' : w = %d h = %d cols %d : ptsize = %d\n",
1347  aChar,a_raster.width,a_raster.rows,a_raster.cols,getPointSize());
1348  for( int row = (a_raster.rows-1); row >=0; --row ) {
1349  unsigned char* bline = (unsigned char*)a_raster.buffer + row * a_raster.cols;
1350  int icol = 0;
1351  int ibit = 0;
1352  unsigned char byte = (unsigned char)bline[icol];
1353  icol++;
1354  for( int i= 0; i < a_raster.width; ++i ) {
1355  unsigned char v = (byte & (1<<(7-ibit)));
1356  printf("%c",(v?'x':' '));
1357  ibit++;
1358  if(ibit==8) {
1359  ibit = 0;
1360  byte = (unsigned char)bline[icol];
1361  icol++;
1362  }
1363  }
1364  printf("\n");
1365  }
1366  }
1367  }*/
1368 
1369  }
1370 
1371  m_trans_x += float(m_face->glyph->advance.x)*m_scale;
1372  m_trans_y += float(m_face->glyph->advance.y)*m_scale;
1373 
1374  ::FT_Done_Glyph(glyph);
1375 
1376  return true;
1377  }
1378 
1380 
1381  static void GLUAPIENTRY begin_cbk(GLUenum a_which,void* a_this) {
1382  text_freetype& self = *((text_freetype*)a_this);
1383  self.m_mode = a_which;
1384  self.m_pos = self.m_xys.size();
1385 #ifdef TOOLS_SG_TEXT_FREETYPE_DEBUG
1386  self.m_out << "tools::sg::text_freetype::begin_cbk :"
1387  << " which " << a_which
1388  << " GL_TRIANGLE_STRIP " << GL_TRIANGLE_STRIP
1389  << " GL_TRIANGLE_FAN " << GL_TRIANGLE_FAN
1390  << " GL_TRIANGLES " << GL_TRIANGLES
1391  << std::endl;
1392 #endif
1393  }
1394 
1395  static void GLUAPIENTRY vertex_cbk(void* a_vertex,void* a_this) {
1396  text_freetype& self = *((text_freetype*)a_this);
1397  double* vertex = (double*)a_vertex;
1398 #ifdef TOOLS_SG_TEXT_FREETYPE_DEBUG
1399  std::cout << "tools::sg::text_freetype::vertex_cbk :"
1400  << " x " << vertex[0]
1401  << " y " << vertex[1]
1402  << " z " << vertex[2]
1403  << std::endl;
1404 #endif
1405  self.add_xy(float(vertex[0]),float(vertex[1]));
1406  }
1407 
1408  static void GLUAPIENTRY end_cbk(void* a_this){
1409  text_freetype& self = *((text_freetype*)a_this);
1410  size_t num = (self.m_xys.size()-self.m_pos)/2;
1411  if(num) {
1412  triangle_t t(self.m_pos,num);
1413  self.m_triangles.push_back(std::pair<GLUenum,triangle_t>(self.m_mode,t));
1414  }
1415  }
1416 
1417  static void GLUAPIENTRY combine_cbk(double a_coords[3],
1418  void* /*a_vertex_data*/[4],
1419  float /*a_weight*/[4],
1420  void** a_data_out,
1421  void* a_this) {
1422  text_freetype& self = *((text_freetype*)a_this);
1423  double* v = self.add_combine_vec3d(a_coords[0],a_coords[1],a_coords[2]);
1424  //if(!v) ???
1425  *a_data_out = v;
1426  }
1427 
1428  static void GLUAPIENTRY error_cbk(GLUenum,void*) {
1429  //const GLubyte* estring = gluErrorString(aErrorCode);
1430  //::fprintf(stderr, "Tessellation Error: %s\n", estring);
1431  //SbTessContour* This = (SbTessContour*)aThis;
1432  //This->setError(true);
1433  }
1434 
1438 
1442  static int outline_move_to(const FT_Vector* a_to,void* a_this){
1443  // NOTE : get x coords in units of wchar,
1444  // get y coords in units of hchar.
1445  // Exa : if char_width is 100*64 get some x of
1446  // the same magnitude (in [0,6400]).
1447  text_freetype& self = *((text_freetype*)a_this);
1448 
1449  //self.m_out << "tools::sg::text_freetype::outline_move_to :"
1450  // << " x " << a_to->x
1451  // << " y " << a_to->y
1452  // << std::endl;
1453 
1454  float gx,gy;
1455  self.set_g(gx,gy,float(a_to->x),float(a_to->y));
1456 
1457  if(self.m_tobj) {
1458  if(self.m_contour_open) {
1460  self.m_contour_open = false;
1461  }
1462 
1464  self.m_contour_open = true;
1465 
1466  {double* v = self.add_glutess_vec3d(gx,gy,0);
1467  ::gluTessVertex(self.m_tobj,v,v);}
1468 
1469  } else {
1470  self.flush_line();
1471  self.add_xy(gx,gy);
1472  }
1473 
1474  self.m_last_x = float(a_to->x);
1475  self.m_last_y = float(a_to->y);
1476 
1477  return 0;
1478  }
1479  static int outline_line_to(const FT_Vector* a_to,void* a_this){
1480  text_freetype& self = *((text_freetype*)a_this);
1481 
1482  //self.m_out << "tools::sg::text_freetype::outline_line_to :"
1483  // << " x " << a_to->x
1484  // << " y " << a_to->y
1485  // << std::endl;
1486 
1487  float gx,gy;
1488  self.set_g(gx,gy,float(a_to->x),float(a_to->y));
1489 
1490  if(self.m_tobj) {
1491  double* v = self.add_glutess_vec3d(gx,gy,0);
1492  ::gluTessVertex(self.m_tobj,v,v);
1493  } else {
1494  self.add_xy(gx,gy);
1495  }
1496 
1497  self.m_last_x = float(a_to->x);
1498  self.m_last_y = float(a_to->y);
1499 
1500  return 0;
1501  }
1502  static int outline_conic_to(const FT_Vector* a_ctrl,const FT_Vector* a_to,void* a_this){
1503  text_freetype& self = *((text_freetype*)a_this);
1504 
1505  // it must be fast. We avoid vec3f manipulations.
1506 
1507  //self.m_out << "tools::sg::text_freetype::outline_conic_to :"
1508  // << " ctrl x " << a_ctrl->x
1509  // << " ctrl y " << a_ctrl->y
1510  // << " x " << a_to->x
1511  // << " y " << a_to->y
1512  // << std::endl;
1513 
1514  float ctrlx = float(a_ctrl->x);
1515  float ctrly = float(a_ctrl->y);
1516 
1517  float fromx = self.m_last_x;
1518  float fromy = self.m_last_y;
1519 
1520  float tox = float(a_to->x);
1521  float toy = float(a_to->y);
1522 
1523  // logic taken from OGLFT.
1524 
1525  //OPTIMIZE :
1526  //b = from - 2 * ctrl + to;
1527  //c = -2 * from + 2 * ctrl;
1528  //df = c * self.m_delta + b * self.m_delta2;
1529  //df2 = 2 * b * self.m_delta2;
1530  float bx = fromx - 2 * ctrlx + tox;
1531  float by = fromy - 2 * ctrly + toy;
1532 
1533  float cx = -2 * fromx + 2 * ctrlx;
1534  float cy = -2 * fromy + 2 * ctrly;
1535 
1536  float dfx = cx * self.m_delta + bx * self.m_delta2;
1537  float dfy = cy * self.m_delta + by * self.m_delta2;
1538 
1539  float df2x = 2 * bx * self.m_delta2;
1540  float df2y = 2 * by * self.m_delta2;
1541 
1542  // if steps = 4, num = 3
1543  // from (i=0) (i=1) (i=2) (to)
1544  // then we have four steps between [from,to]
1545 
1546  // from = starting point.
1547 
1548  float gx,gy;
1549 
1550  size_t num = self.m_steps - 1;
1551  for(size_t i=0;i<num;i++) {
1552  fromx += dfx;
1553  fromy += dfy;
1554 
1555  self.set_g(gx,gy,fromx,fromy);
1556 
1557  if(self.m_tobj) {
1558  double* v = self.add_glutess_vec3d(gx,gy,0);
1559  ::gluTessVertex(self.m_tobj,v,v);
1560  } else {
1561  self.add_xy(gx,gy);
1562  }
1563 
1564  dfx += df2x;
1565  dfy += df2y;
1566  }
1567 
1568  //g = to;
1569  self.set_g(gx,gy,tox,toy);
1570 
1571  if(self.m_tobj) {
1572  double* v = self.add_glutess_vec3d(gx,gy,0);
1573  ::gluTessVertex(self.m_tobj,v,v);
1574  } else {
1575  self.add_xy(gx,gy);
1576  }
1577 
1578  //self.m_last = to;
1579  self.m_last_x = tox;
1580  self.m_last_y = toy;
1581 
1582  return 0;
1583  }
1584  void set_g(float& a_gx,float& a_gy,float a_x,float a_y) const {
1585  a_gx = a_x*m_scale+m_trans_x;
1586  a_gy = a_y*m_scale+m_trans_y;
1587  }
1588  static int outline_cubic_to(const FT_Vector* a_ctrl1,const FT_Vector* a_ctrl2,const FT_Vector* a_to,void* a_this){
1589  text_freetype& self = *((text_freetype*)a_this);
1590 
1591  // it must be fast. We avoid vec3f manipulations.
1592 
1593  //self.m_out << "tools::sg::text_freetype::outline_cubic_to :"
1594  // << " ctrl1 x " << a_ctrl1->x
1595  // << " ctrl1 y " << a_ctrl1->y
1596  // << " ctrl2 x " << a_ctrl2->x
1597  // << " ctrl2 y " << a_ctrl2->y
1598  // << " x " << a_to->x
1599  // << " y " << a_to->y
1600  // << std::endl;
1601 
1602  float ctrl1x = float(a_ctrl1->x);
1603  float ctrl1y = float(a_ctrl1->y);
1604 
1605  float ctrl2x = float(a_ctrl2->x);
1606  float ctrl2y = float(a_ctrl2->y);
1607 
1608  float fromx = self.m_last_x;
1609  float fromy = self.m_last_y;
1610 
1611  float tox = float(a_to->x);
1612  float toy = float(a_to->y);
1613 
1614  // logic taken from OGLFT.
1615 
1616  //OPTIMIZE :
1617  //a = -from + 3 * ctrl1 - 3 * ctrl2 + to;
1618  //b = 3 * from - 6 * ctrl1 + 3 * ctrl2;
1619  //c = -3 * from + 3 * ctrl1;
1620  //df = c * self.m_delta + b * self.m_delta2 + a * self.m_delta3;
1621  //df2 = 2 * b * self.m_delta2 + 6 * a * self.m_delta3;
1622  //df3 = 6 * a * self.m_delta3;
1623 
1624  float ax = -fromx + 3 * ctrl1x - 3 * ctrl2x + tox;
1625  float ay = -fromy + 3 * ctrl1y - 3 * ctrl2y + toy;
1626 
1627  float bx = 3 * fromx - 6 * ctrl1x + 3 * ctrl2x;
1628  float by = 3 * fromy - 6 * ctrl1y + 3 * ctrl2y;
1629 
1630  float cx = -3 * fromx + 3 * ctrl1x;
1631  float cy = -3 * fromy + 3 * ctrl1y;
1632 
1633  float dfx = cx * self.m_delta + bx * self.m_delta2 + ax * self.m_delta3;
1634  float dfy = cy * self.m_delta + by * self.m_delta2 + ay * self.m_delta3;
1635 
1636  float df2x = 2 * bx * self.m_delta2 + 6 * ax * self.m_delta3;
1637  float df2y = 2 * by * self.m_delta2 + 6 * ay * self.m_delta3;
1638 
1639  float df3x = 6 * ax * self.m_delta3;
1640  float df3y = 6 * ay * self.m_delta3;
1641 
1642  // if steps = 4, num = 3
1643  // from (i=0) (i=1) (i=2) (to)
1644  // then we have four steps between [from,to]
1645 
1646  // from = starting point.
1647  float gx,gy;
1648 
1649  size_t num = self.m_steps - 1;
1650  for(size_t i=0;i<num;i++) {
1651  fromx += dfx;
1652  fromy += dfy;
1653 
1654  self.set_g(gx,gy,fromx,fromy);
1655 
1656  if(self.m_tobj) {
1657  double* v = self.add_glutess_vec3d(gx,gy,0);
1658  ::gluTessVertex(self.m_tobj,v,v);
1659  } else {
1660  self.add_xy(gx,gy);
1661  }
1662 
1663  dfx += df2x;
1664  dfy += df2y;
1665 
1666  df2x += df3x;
1667  df2y += df3y;
1668  }
1669 
1670  //g = to;
1671  self.set_g(gx,gy,tox,toy);
1672 
1673  if(self.m_tobj) {
1674  double* v = self.add_glutess_vec3d(gx,gy,0);
1675  ::gluTessVertex(self.m_tobj,v,v);
1676  } else {
1677  self.add_xy(gx,gy);
1678  }
1679 
1680  //self.m_last = to;
1681  self.m_last_x = tox;
1682  self.m_last_y = toy;
1683 
1684  return 0;
1685  }
1686 
1687 
1688 public:
1689 #ifndef SWIG
1690  class serrors : public std::map<int,std::string> {
1691  typedef std::map<int,std::string> parent;
1692  public:
1694 #undef __FTERRORS_H__
1695 #define FT_ERROR_START_LIST
1696 #define FT_ERROR_END_LIST
1697 #define FT_ERRORDEF( e, v, s ) parent::operator[](e) = s;
1698 #include FT_ERRORS_H
1699  }
1700  virtual ~serrors() {}
1701  protected:
1702  serrors(const serrors& a_from):parent(a_from) {}
1703  serrors& operator=(const serrors&){return *this;}
1704  };
1705  static std::string serror(int a_FT_Error) {
1706  static const serrors errs;
1707  std::map<int,std::string>::const_iterator it = errs.find(a_FT_Error);
1708  if(it!=errs.end()) return (*it).second;
1709  return "unknown";
1710  }
1711 #endif
1712 protected:
1713  void add_xy(float a_x,float a_y) {
1714  m_xys.push_back(a_x);
1715  m_xys.push_back(a_y);
1716  }
1717 
1718  double* add_glutess_vec3d(float a_x,float a_y,float a_z) {
1719  double* v = 0;
1720  if(m_glutess_trids_num>=m_glutess_trids.size()) {
1721  v = new double[3];
1722  m_glutess_trids.push_back(v);
1723  } else {
1725  }
1727 
1728  v[0] = a_x;
1729  v[1] = a_y;
1730  v[2] = a_z;
1731 
1732  return v;
1733  }
1734 
1735  double* add_combine_vec3d(double a_x,double a_y,double a_z) {
1736  double* v = 0;
1737  if(m_combine_trids_num>=m_combine_trids.size()) {
1738  v = new double[3];
1739  m_combine_trids.push_back(v);
1740  } else {
1742  }
1744 
1745  v[0] = a_x;
1746  v[1] = a_y;
1747  v[2] = a_z;
1748 
1749  return v;
1750  }
1751 
1752  void clear_trids() {
1753  {tools_vforit(double*,m_glutess_trids,it) delete [] *it;
1754  m_glutess_trids.clear();}
1755 
1756  {tools_vforit(double*,m_combine_trids,it) delete [] *it;
1757  m_combine_trids.clear();}
1758  }
1759 
1760  void load_face(std::ostream& a_out) {
1761  if(!m_library) {
1762  a_out << "tools::sg::text_freetype::load_face :"
1763  << " freetype library not initialized."
1764  << std::endl;
1765  return;
1766  }
1767 
1768  if(m_verbose) {
1769  a_out << "tools::sg::text_freetype::load_face :"
1770  << " font is " << tools::sout(font.value()) << "."
1771  << std::endl;
1772  }
1773 
1774  if(m_face) {
1775  ::FT_Done_Face(m_face);
1776  m_face = 0;
1777  }
1778  if(font.value().empty()) {
1779  a_out << "tools::sg::text_freetype::load_face :"
1780  << " no font file given."
1781  << std::endl;
1782  return;
1783  }
1784 
1785  std::string file;
1786 
1787  //if(tools::file::exists(font.value())) { //look in current directory.
1788  // file = font.value(); //ok
1789  //} else if(!inlib::find_with_dirs(a_out,font_dirs.values(),font.value(),file,false)) {
1790  if(!tools::find_with_env(a_out,s_TOOLS_FONT_PATH(),font.value(),file,false)) {
1791  a_out << "tools::sg::text_freetype::load_face :"
1792  << " font file not found for font "
1793  << tools::sout(font.value()) << "."
1794  << std::endl;
1795  return;
1796  }
1797  //}
1798 
1799  if(m_verbose) {
1800  a_out << "tools::sg::text_freetype::load_face :"
1801  << " load font file " << tools::sout(file) << " ..."
1802  << std::endl;
1803  }
1804 
1805  FT_Error error = ::FT_New_Face(m_library,file.c_str(),0,&m_face);
1806  if(error) {
1807  a_out << "tools::sg::text_freetype::load_face :"
1808  << " FT_New_Face : error : " << serror(error) << "."
1809  << " for font file " << tools::sout(file) << "."
1810  << std::endl;
1811  m_face = 0;
1812  return;
1813  }
1814 
1815  if(m_verbose) {
1816  a_out << "tools::sg::text_freetype::load_face :"
1817  << " load ok."
1818  << std::endl;
1819  }
1820 
1821  }
1822 
1823 protected:
1824  static int load_flags() {
1825  return FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
1826  //return FT_LOAD_DEFAULT;
1827  //return FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP;
1828  }
1829 
1830  static bool set_char_size(std::ostream& a_out,FT_Face& a_face,float a_height,float& a_scale) {
1831 
1832  // arrange char_width, char_height and m_scale so
1833  // that text height be 1 in world coordinates.
1834 
1835  // What these fancy 26.6, 64, 72 number mean ?
1836  // In what unit do we receive points in callbacks ?
1837  // Knowing char_height and vres can we know height of points ?
1838 
1839  FT_F26Dot6 wchar = 1000*64;
1840  FT_F26Dot6 hchar = 1000*64;
1841  FT_UInt hres = 72;
1842  FT_UInt vres = 72;
1843 
1844  FT_Error error = ::FT_Set_Char_Size(a_face,wchar,hchar,hres,vres);
1845  if(error) {
1846  a_out << "tools::sg::text_freetype::set_char_size :"
1847  << " FT_Set_Char_Size : error : " << serror(error) << "."
1848  << std::endl;
1849  ::FT_Done_Face(a_face);
1850  a_face = 0;
1851  a_scale = 1;
1852  return false;
1853  }
1854  a_scale = a_height/float(wchar);
1855  return true;
1856  }
1857 
1858  static bool ascent(std::ostream& a_out,FT_Face& a_face,float a_height,float& a_value) {
1859  float scale;
1860  if(!set_char_size(a_out,a_face,a_height,scale)) {a_value = 0;return false;}
1861  FT_Pos ascent = a_face->size->metrics.ascender; //FT_Pos (long)
1862  a_value = float(ascent) * scale;
1863  return true;
1864  }
1865 
1866  static bool descent(std::ostream& a_out,FT_Face& a_face,float a_height,float& a_value) {
1867  float scale;
1868  if(!set_char_size(a_out,a_face,a_height,scale)) {a_value = 0;return false;}
1869  FT_Pos descent = a_face->size->metrics.descender; //FT_Pos (long) //<0
1870  a_value = -(float(descent) * scale);
1871  return true;
1872  }
1873 
1874  static bool y_advance(std::ostream& a_out,FT_Face& a_face,float a_height,float& a_adv) {
1875  float scale;
1876  if(!set_char_size(a_out,a_face,a_height,scale)) {a_adv = 0;return false;}
1877  FT_Pos face_height = a_face->size->metrics.height; //FT_Pos (long)
1878  a_adv = float(face_height)*scale;
1879  return true;
1880  }
1881 
1882  static bool truncate(std::ostream& a_out,FT_Face& a_face,float a_height,
1883  const std::string& a_string,float a_cut_width,std::string& a_sout) {
1884  a_sout.clear();
1885 
1886  float scale;
1887  if(!set_char_size(a_out,a_face,a_height,scale)) return false;
1888 
1889  float width = 0;
1890 
1891  unsigned short offset;
1892  if(!encoding_offset(a_face,offset)) return false;
1893 
1894  tools_sforcit(a_string,it) {
1895  FT_ULong charcode = *it + offset; //charcode is UTF-32.
1896  FT_UInt glyph_index = ::FT_Get_Char_Index(a_face,charcode);
1897  //NOTE : if not found -> glyph_index = 0 which is the "missing glyph".
1898  if((FT_Long)glyph_index>=a_face->num_glyphs) {
1899 #ifdef TOOLS_SG_TEXT_FREETYPE_DEBUG
1900  m_out << "tools::sg::text_freetype::truncate :"
1901  << " FT_Get_Char_Index : failed for char : " << *it
1902  << std::endl;
1903 #endif
1904  a_sout.clear();
1905  ::FT_Done_Face(a_face);
1906  a_face = 0;
1907  return false;
1908  }
1909 
1910  {FT_Error error = ::FT_Load_Glyph(a_face,glyph_index,load_flags());
1911  if(error) {
1912 #ifdef TOOLS_SG_TEXT_FREETYPE_DEBUG
1913  m_out << "tools::sg::text_freetype::truncate :"
1914  << " for character " << *it
1915  << ",FT_Load_Glyph : error : " << serror(error)
1916  << std::endl;
1917 #endif
1918  a_sout.clear();
1919  ::FT_Done_Face(a_face);
1920  a_face = 0;
1921  return false;
1922  }}
1923 
1924  float cwidth = float(a_face->glyph->metrics.width)*scale;
1925  float advance = float(a_face->glyph->advance.x)*scale;
1926  if((width+cwidth)>=a_cut_width) return true;
1927  a_sout += *it;
1928  width += advance;
1929  }
1930 
1931  return true;
1932  }
1933 
1934  static bool get_bounds(std::ostream& a_out,FT_Face& a_face,float a_height,
1935  const std::vector<std::string>& a_text,
1936  float& a_mn_x,float& a_mn_y,float& a_mn_z,
1937  float& a_mx_x,float& a_mx_y,float& a_mx_z){
1938  tools::box_3f_make_empty(a_mn_x,a_mn_y,a_mn_z,a_mx_x,a_mx_y,a_mx_z);
1939 
1940  if(a_text.empty()) return true;
1941 
1942  float scale;
1943  if(!set_char_size(a_out,a_face,a_height,scale)) return false;
1944 
1945  float xmx = 0;
1946 
1947  unsigned short offset;
1948  if(!encoding_offset(a_face,offset)) return false;
1949 
1950  tools_vforcit(std::string,a_text,vit) {
1951  const std::string& line = *vit;
1952 
1953  float width = 0;
1954  tools_sforcit(line,it) {
1955  FT_ULong charcode = *it + offset; //charcode is UTF-32.
1956  FT_UInt glyph_index = ::FT_Get_Char_Index(a_face,charcode);
1957  //NOTE : if not found -> glyph_index = 0 which is the "missing glyph".
1958  if((FT_Long)glyph_index>=a_face->num_glyphs) {
1959  ::FT_Done_Face(a_face);
1960  a_face = 0;
1961  return false;
1962  }
1963 
1964  {FT_Error error = ::FT_Load_Glyph(a_face,glyph_index,load_flags());
1965  if(error) {
1966  ::FT_Done_Face(a_face);
1967  a_face = 0;
1968  return false;
1969  }}
1970 
1971  //float cwidth = float(a_face->glyph->metrics.width)*scale;
1972  float advance = float(a_face->glyph->advance.x)*scale;
1973  width += advance;
1974  }
1975 
1976  xmx = tools::mx<float>(xmx,width);
1977  }
1978 
1979  FT_Pos ascent = a_face->size->metrics.ascender; //FT_Pos (long)
1980  FT_Pos descent = a_face->size->metrics.descender; //FT_Pos (long) //<0
1981  FT_Pos face_height = a_face->size->metrics.height; //FT_Pos (long)
1982 
1983  float ymn = -float(face_height)*scale*(a_text.size()-1) //height>0
1984  +float(descent)*scale;
1985 
1986  a_mn_x = 0;
1987  a_mn_y = ymn;
1988  a_mn_z = 0;
1989  a_mx_x = xmx;
1990  a_mx_y = float(ascent)*scale;
1991  a_mx_z = 0;
1992 
1993  return true;
1994  }
1995 
1996  static bool get_bounds(std::ostream& a_out,FT_Face& a_face,float a_height,
1997  const std::vector<uniline>& a_text,
1998  float& a_mn_x,float& a_mn_y,float& a_mn_z,
1999  float& a_mx_x,float& a_mx_y,float& a_mx_z){
2000  tools::box_3f_make_empty(a_mn_x,a_mn_y,a_mn_z,a_mx_x,a_mx_y,a_mx_z);
2001 
2002  if(a_text.empty()) return true;
2003 
2004  float scale;
2005  if(!set_char_size(a_out,a_face,a_height,scale)) return false;
2006 
2007  float xmx = 0;
2008 
2009  tools_vforcit(uniline,a_text,vit) {
2010  const uniline& line = *vit;
2011  float width = 0;
2012 
2013  tools_vforcit(unichar,line,it) {
2014 
2015  FT_ULong charcode = *it; //charcode is UTF-32.
2016  FT_UInt glyph_index = ::FT_Get_Char_Index(a_face,charcode);
2017  //NOTE : if not found -> glyph_index = 0 which is the "missing glyph".
2018  if((FT_Long)glyph_index>=a_face->num_glyphs) {
2019  ::FT_Done_Face(a_face);
2020  a_face = 0;
2021  return false;
2022  }
2023 
2024  {FT_Error error = ::FT_Load_Glyph(a_face,glyph_index,load_flags());
2025  if(error) {
2026  ::FT_Done_Face(a_face);
2027  a_face = 0;
2028  return false;
2029  }}
2030 
2031  //float cwidth = float(a_face->glyph->metrics.width)*scale;
2032  float advance = float(a_face->glyph->advance.x)*scale;
2033  width += advance;
2034  }
2035 
2036  xmx = tools::mx<float>(xmx,width);
2037  }
2038 
2039  FT_Pos ascent = a_face->size->metrics.ascender; //FT_Pos (long)
2040  FT_Pos descent = a_face->size->metrics.descender; //FT_Pos (long) //<0
2041  FT_Pos face_height = a_face->size->metrics.height; //FT_Pos (long)
2042 
2043  float ymn = -float(face_height)*scale*(a_text.size()-1) //height>0
2044  +float(descent)*scale;
2045 
2046  a_mn_x = 0;
2047  a_mn_y = ymn;
2048  a_mn_z = 0;
2049  a_mx_x = xmx;
2050  a_mx_y = float(ascent)*scale;
2051  a_mx_z = 0;
2052 
2053  return true;
2054  }
2055 
2056  static bool encoding_offset(FT_Face& a_face,unsigned short& a_offset) {
2057 
2058  // arialbd.ttf :
2059  // num charmap 2
2060  // charmap 0, platform 1, encoding 0.
2061  // charmap 1, platform 3, encoding 1.
2062 
2063  // symbol.ttf :
2064  // num charmap 2
2065  // charmap 0, platform 1, encoding 0.
2066  // charmap 1, platform 3, encoding 0.
2067 
2068  // stixgeneral.otf :
2069  // num charmap 6.
2070  // charmap 0, platform 0, encoding 3.
2071  // charmap 1, platform 0, encoding 4.
2072  // charmap 2, platform 1, encoding 0.
2073  // charmap 3, platform 3, encoding 1.
2074 
2075  a_offset = 0;
2076 
2077  //std::cout << "tools::sg::text_freetype::encoding_offset :"
2078  // << " num charmap " << a_face->num_charmaps << "."
2079  // << std::endl;
2080 
2081  // cooking to handle symbol.ttf and wingding.ttf :
2082  FT_Int n = a_face->num_charmaps;
2083  FT_Int i;
2084  for ( i = 0; i < n; i++ ) {
2085  FT_CharMap charmap = a_face->charmaps[i];
2086  unsigned short platform = charmap->platform_id;
2087  unsigned short encoding = charmap->encoding_id;
2088 
2089  //std::cout << "tools::sg::text_freetype::encoding_offset :"
2090  // << " for charmap " << i
2091  // << ", platform " << platform
2092  // << ", encoding " << encoding << "."
2093  // << std::endl;
2094 
2095  if ( (platform == 3 && encoding == 1 ) ||
2096  (platform == 3 && encoding == 0 ) ||
2097  //(platform == 1 && encoding == 0 ) ||
2098  (platform == 0 && encoding == 0 ) ) {
2099  FT_Error error = FT_Set_Charmap(a_face,charmap);
2100  if(error) {
2101  ::FT_Done_Face(a_face);
2102  a_face = 0;
2103  a_offset = 0;
2104  return false;
2105  }
2106  // For symbol.ttf and wingding.ttf
2107  if (platform == 3 && encoding == 0 ) a_offset = 0xF000;
2108  //if (platform == 1 && encoding == 0 ) a_offset = 0xF000;
2109  return true;
2110 
2111  } else {
2112  //SoDebugError::post("SbTextTTF2Face::loadFont",
2113  // "for \"%s\", platform %d and encoding %d not taken into account",
2114  // filename,platform,encoding);
2115  }
2116  }
2117 
2118  //a_out << "tools::sg::text_freetype::update_sg :"
2119  // << " This font doesn't contain any Unicode mapping table."
2120  // << std::endl;
2121  ::FT_Done_Face(a_face);
2122  a_face = 0;
2123  a_offset = 0;
2124  return false;
2125  }
2126 
2127 protected:
2128  FT_Library m_library;
2129  FT_Face m_face;
2130  unsigned short m_encoding_offset;
2131  bool m_verbose; //append _ to avoid clash with inlib/sg/guib::m_verbose
2135  FT_Outline_Funcs m_funcs; //See doc in ftimage.h
2137  float m_scale;
2139  size_t m_steps;
2140  float m_delta;
2141  float m_delta2;
2142  float m_delta3;
2143 
2144  std::vector<float> m_xys;
2148  typedef std::pair<size_t,size_t> line_t; //pos in m_xys.
2149  typedef std::vector<line_t> lines_t;
2156  std::vector<double*> m_glutess_trids;
2158  std::vector<double*> m_combine_trids;
2161  typedef std::pair<size_t,size_t> triangle_t; //pos in m_xys.
2162  typedef std::pair<GLUenum,triangle_t> gl_triangle_t;
2163  typedef std::vector<gl_triangle_t> triangles_t;
2165  size_t m_pos;
2167  size_t m_gsto_sz;
2171  std::vector<tools::sg::tex_quadrilateral*> m_tqs;
2173 };
2174 
2175 }}
2176 
2177 #endif
tools::sg::text_freetype::descent
virtual float descent(float a_height) const
Definition: text_freetype:463
tools::nostream
Definition: nostream:16
tools::sg::text_freetype::char_height_touched
bool char_height_touched(const tools::sg::state &a_state)
Definition: text_freetype:579
tools::sg::text_freetype::gl_triangle_t
std::pair< GLUenum, triangle_t > gl_triangle_t
Definition: text_freetype:2162
fmanip
tools::sg::render_action::set_line_smooth
virtual void set_line_smooth(bool)=0
tools::sg::text_freetype::truncate
virtual bool truncate(const std::string &a_string, float a_height, float a_cut_width, std::string &a_out) const
Definition: text_freetype:506
tools::sg::hchar
Definition: text_hershey:23
platform
tools::byte
unsigned char byte
Definition: typedefs:96
tools::sg::text_freetype::m_lines
lines_t m_lines
Definition: text_freetype:2150
tools::sg::font_pixmap
@ font_pixmap
Definition: enums:94
tools::sg::text_freetype::outline_move_to
static int outline_move_to(const FT_Vector *a_to, void *a_this)
outline triangles : end ////////////////////////////
Definition: text_freetype:1442
tools::value
Definition: value:18
_GLUfuncptr
void(* _GLUfuncptr)()
Definition: _glu:49
gluTessCallback_GLU_TESS_VERTEX_DATA
void GLUAPIENTRY gluTessCallback_GLU_TESS_VERTEX_DATA(GLUtesselator *tess, void(GLUAPIENTRY *a_fn)(void *, void *))
Definition: glutess:246
tools::sg::text_freetype::set_g
void set_g(float &a_gx, float &a_gy, float a_x, float a_y) const
Definition: text_freetype:1584
tools::sg::render_action::draw_gsto_v
virtual void draw_gsto_v(gl::mode_t, size_t, bufpos)=0
gluTessCallback_GLU_TESS_COMBINE_DATA
void GLUAPIENTRY gluTessCallback_GLU_TESS_COMBINE_DATA(GLUtesselator *tess, void(GLUAPIENTRY *a_fn)(GLUdouble[3], void *[4], GLUfloat[4], void **, void *))
Definition: glutess:262
tools::sg::state
Definition: state:25
tools::colorf::guchar
uchar guchar() const
Definition: colorf:43
tools::sg::text_freetype::m_front_color
tools::colorf m_front_color
Definition: text_freetype:2169
tools::sg::text_freetype::m_triangles
triangles_t m_triangles
Definition: text_freetype:2164
tools::sg::base_freetype::uniline
std::vector< unichar > uniline
Definition: base_freetype:23
tools::sg::text_freetype::m_char_height
float m_char_height
Definition: text_freetype:2172
tools::gl::triangle_strip_to_triangles_2to3
void triangle_strip_to_triangles_2to3(size_t a_npt, const float *a_xyzs, float *&a_pxyzs)
Definition: glprims:346
TOOLS_CLASS_STRING
#define TOOLS_CLASS_STRING(a_name)
Definition: S_STRING:11
tools::sg::text_freetype::m_mode
GLUenum m_mode
Definition: text_freetype:2160
tools::gl::triangles
mode_t triangles()
Definition: glprims:20
gluTessCallback
GLUAPI void GLUAPIENTRY gluTessCallback(GLUtesselator *tess, GLUenum which, _GLUfuncptr CallBackFunc)
Definition: glutess:269
tools::sg::text_freetype::m_delta3
float m_delta3
Definition: text_freetype:2142
tools::sg::winding_ccw
@ winding_ccw
Definition: enums:105
GLU_TESS_COMBINE_DATA
#define GLU_TESS_COMBINE_DATA
Definition: _glu:31
tools::sg::group::bbox
virtual void bbox(bbox_action &a_action)
Definition: group:42
tools::sg::text_freetype::clear_trids
void clear_trids()
Definition: text_freetype:1752
tools::sg::text_freetype::serrors::operator=
serrors & operator=(const serrors &)
Definition: text_freetype:1703
tools::sg::text_freetype::y_advance
virtual float y_advance(float a_height) const
Definition: text_freetype:476
tools::sg::text_freetype::m_face
FT_Face m_face
Definition: text_freetype:2129
tools::sg::text_freetype::create_gsto
virtual unsigned int create_gsto(std::ostream &a_out, tools::sg::render_manager &a_mgr)
Definition: text_freetype:82
tools::sg::blend::on
sf< bool > on
Definition: blend:19
pick_action
tools::sg::text_freetype::wndg_ccw
@ wndg_ccw
Definition: text_freetype:77
tools::sg::text_freetype::get_bounds
static bool get_bounds(std::ostream &a_out, FT_Face &a_face, float a_height, const std::vector< std::string > &a_text, float &a_mn_x, float &a_mn_y, float &a_mn_z, float &a_mx_x, float &a_mx_y, float &a_mx_z)
Definition: text_freetype:1934
tools::sg::tex_quadrilateral
Definition: tex_quadrilateral:23
tools::colorf
Definition: colorf:11
tools::sg::base_text::height
sf< float > height
Definition: base_text:30
tools::sg::hjust
hjust
Definition: enums:73
tools::sg::text_freetype::add_combine_vec3d
double * add_combine_vec3d(double a_x, double a_y, double a_z)
Definition: text_freetype:1735
tools::sg::text_freetype::m_library
FT_Library m_library
Definition: text_freetype:2128
render_action
tools::sg::tex_quadrilateral::corners
mf_vec< vec3f, float > corners
Definition: tex_quadrilateral:33
tools::sg::state::m_GL_POLYGON_OFFSET_FILL
bool m_GL_POLYGON_OFFSET_FILL
Definition: state:250
tools::gl::triangle_fan
mode_t triangle_fan()
Definition: glprims:22
tools::sg::text_freetype::m_combine_trids
std::vector< double * > m_combine_trids
Definition: text_freetype:2158
tools::sg::text_freetype::text_freetype
text_freetype()
Definition: text_freetype:399
tools::sg::base_freetype::modeling
sf_enum< font_modeling > modeling
Definition: base_freetype:21
tools::sg::gstos::clean_gstos
void clean_gstos()
Definition: gstos:89
tools::sg::node
Definition: node:28
tools::sg::text_freetype::char_triangles_2_gl
bool char_triangles_2_gl(std::ostream &a_out, unsigned int a_unichar)
Definition: text_freetype:975
tools::sg::base_freetype::unichar
unsigned int unichar
Definition: base_freetype:22
tools::gl::lines
mode_t lines()
Definition: glprims:17
tools::sg::bbox_action
Definition: bbox_action:15
TOOLS_NODE
#define TOOLS_NODE(a__class, a__sclass, a__parent)
Definition: node:324
tools::sg::text_freetype::faces
@ faces
Definition: text_freetype:567
gluTessBeginPolygon
GLUAPI void GLUAPIENTRY gluTessBeginPolygon(GLUtesselator *tess, GLUvoid *data)
Definition: glutess:455
tools::sg::primitive_visitor::add_one_point
void add_one_point(float a_x, float a_y, float a_z)
Definition: primitive_visitor:63
GLUAPIENTRY
#define GLUAPIENTRY
Definition: _glu:48
tools::sg::group
Definition: group:21
tools::sg::text_freetype::m_contour_open
bool m_contour_open
Definition: text_freetype:2155
tools::sg::text_freetype::text_freetype
text_freetype(const text_freetype &a_from)
Definition: text_freetype:418
tools::gl::triangle_fan_to_triangles_2to3
void triangle_fan_to_triangles_2to3(size_t a_npt, const float *a_xyzs, float *&a_pxyzs)
Definition: glprims:313
tools::sg::text_freetype::color_touched
bool color_touched(const tools::sg::state &a_state)
Definition: text_freetype:572
tools::sg::text_freetype::m_glutess_trids
std::vector< double * > m_glutess_trids
Definition: text_freetype:2156
tools::sg::render_action::set_winding
virtual void set_winding(winding_type)=0
tools::box_3f_make_empty
void box_3f_make_empty(float &a_mn_x, float &a_mn_y, float &a_mn_z, float &a_mx_x, float &a_mx_y, float &a_mx_z)
Definition: box_3f:15
tools::sg::state::m_winding
winding_type m_winding
Definition: state:258
tools::sg::right
@ right
Definition: enums:76
tools::sg::text_freetype::m_wndg
wndg_type m_wndg
Definition: text_freetype:2168
tools::sg::base_freetype
Definition: base_freetype:16
tools::sg::base_tex::back_color
sf_vec< colorf, float > back_color
Definition: base_tex:29
group
tools::find_with_env
bool find_with_env(std::ostream &a_out, const std::string &a_env, const std::string &a_file, std::string &a_path, bool a_verbose=false)
Definition: fmanip:64
tools::sg::text_freetype::truncate
static bool truncate(std::ostream &a_out, FT_Face &a_face, float a_height, const std::string &a_string, float a_cut_width, std::string &a_sout)
Definition: text_freetype:1882
tools::sg::text_freetype::load_face
void load_face(std::ostream &a_out)
Definition: text_freetype:1760
tools::sg::text_freetype::m_trans_y
float m_trans_y
Definition: text_freetype:2138
tools::sg::text_freetype::end_cbk
static void GLUAPIENTRY end_cbk(void *a_this)
Definition: text_freetype:1408
tools::gl::line_strip
mode_t line_strip()
Definition: glprims:19
tools::sg::blend
Definition: blend:16
gluTessCallback_GLU_TESS_ERROR_DATA
void GLUAPIENTRY gluTessCallback_GLU_TESS_ERROR_DATA(GLUtesselator *tess, void(GLUAPIENTRY *a_fn)(GLUenum, void *))
Definition: glutess:258
tools::sg::text_freetype::error_cbk
static void GLUAPIENTRY error_cbk(GLUenum, void *)
Definition: text_freetype:1428
tools::sg::top
@ top
Definition: enums:82
tools::sg::text_freetype::serror
static std::string serror(int a_FT_Error)
Definition: text_freetype:1705
tools::sg::text_freetype::m_tqs
std::vector< tools::sg::tex_quadrilateral * > m_tqs
Definition: text_freetype:2171
tools::sg::text_freetype::outline_line_to
static int outline_line_to(const FT_Vector *a_to, void *a_this)
Definition: text_freetype:1479
tools::sg::render_action::color4f
virtual void color4f(float, float, float, float)=0
tools::sg::text_freetype::m_combine_trids_num
size_t m_combine_trids_num
Definition: text_freetype:2159
tools::sg::winding_cw
@ winding_cw
Definition: enums:106
tools::sg::node::operator=
node & operator=(const node &)
Definition: node:124
tools::sg::bmf::values
const std::vector< T > & values() const
Definition: bmf:71
tools::sg::field::touched
bool touched() const
Definition: field:60
tools::sg::text_freetype::m_gsto_lines_sz
size_t m_gsto_lines_sz
Definition: text_freetype:2166
tools::sg::text_freetype::set_char_size
static bool set_char_size(std::ostream &a_out, FT_Face &a_face, float a_height, float &a_scale)
Definition: text_freetype:1830
tools::sg::text_freetype::m_funcs
FT_Outline_Funcs m_funcs
outline ////////////////////////////////////////////
Definition: text_freetype:2135
tools::sg::base_tex::img
sf_img< byte > img
Definition: base_tex:28
tools::sg::pick_action
Definition: pick_action:59
tools::sg::text_freetype::m_pos
size_t m_pos
Definition: text_freetype:2165
tools::sg::text_freetype::m_tobj
GLUtesselator * m_tobj
outline triangles //////////////////////////////////
Definition: text_freetype:2154
tools::sg::render_manager::create_gsto_from_data
virtual unsigned int create_gsto_from_data(size_t, const float *)=0
tools::sg::text_freetype::serrors
Definition: text_freetype:1690
tools::sg::group::render
virtual void render(render_action &a_action)
Definition: group:24
tools::sg::text_freetype::serrors::serrors
serrors(const serrors &a_from)
Definition: text_freetype:1702
tools::uchar
unsigned char uchar
Definition: typedefs:99
tools::sg::text_freetype::m_delta2
float m_delta2
Definition: text_freetype:2141
tools::sg::state::m_wh
unsigned int m_wh
Definition: state:242
gluTessBeginContour
GLUAPI void GLUAPIENTRY gluTessBeginContour(GLUtesselator *tess)
Definition: glutess:469
tools::sg::state::m_use_gsto
bool m_use_gsto
Definition: state:256
tools::sout
Definition: sout:17
GLU_TESS_ERROR_DATA
#define GLU_TESS_ERROR_DATA
Definition: _glu:30
tools::gl::triangle_strip
mode_t triangle_strip()
Definition: glprims:21
tools::sg::text_freetype::initialize
bool initialize()
Definition: text_freetype:534
tools::sg::text_freetype::m_steps
size_t m_steps
Definition: text_freetype:2139
tools::sg::render_manager
Definition: render_manager:16
base_freetype
GLU_TESS_WINDING_ODD
#define GLU_TESS_WINDING_ODD
Definition: _glu:38
box_3f
tools::sg::text_freetype::descent
static bool descent(std::ostream &a_out, FT_Face &a_face, float a_height, float &a_value)
Definition: text_freetype:1866
tools::sg::text_freetype::m_verbose
bool m_verbose
Definition: text_freetype:2131
tools::sg::text_freetype::m_delta
float m_delta
Definition: text_freetype:2140
tools::sg::text_freetype::outline_conic_to
static int outline_conic_to(const FT_Vector *a_ctrl, const FT_Vector *a_to, void *a_this)
Definition: text_freetype:1502
tools::sg::text_freetype::wndg_not_done
@ wndg_not_done
Definition: text_freetype:79
tools::sg::state::m_GL_LINE_SMOOTH
bool m_GL_LINE_SMOOTH
Definition: state:253
tools::sg::group::add
void add(node *a_node)
Definition: group:96
tools::sg::text_freetype::m_glutess_trids_num
size_t m_glutess_trids_num
Definition: text_freetype:2157
tools::sg::render_action::set_polygon_offset
virtual void set_polygon_offset(bool)=0
tools::sg::base_freetype::font
sf_string font
Definition: base_freetype:19
blend
GLUtesselator
Definition: _tess:27
tools::sg::text_freetype::get_bounds
static bool get_bounds(std::ostream &a_out, FT_Face &a_face, float a_height, const std::vector< uniline > &a_text, float &a_mn_x, float &a_mn_y, float &a_mn_z, float &a_mx_x, float &a_mx_y, float &a_mx_z)
Definition: text_freetype:1996
tools::sg::text_freetype::add_glutess_vec3d
double * add_glutess_vec3d(float a_x, float a_y, float a_z)
Definition: text_freetype:1718
tools::sg::text_freetype::outline_triangles_2_gl
void outline_triangles_2_gl(std::ostream &a_out)
outline triangles //////////////////////////////////
Definition: text_freetype:865
tools::sg::text_freetype::Func
_GLUfuncptr Func
Definition: text_freetype:1379
tools::sg::text_freetype::m_scale
float m_scale
Definition: text_freetype:2137
tools::sg::text_freetype::m_gsto_sz
size_t m_gsto_sz
Definition: text_freetype:2167
tools::sg::pick_action::add__line_strip_xy
bool add__line_strip_xy(sg::node &a_node, size_t a_floatn, const float *a_xys, bool a_stop=false)
Definition: pick_action:386
nostream
tools::sg::render_action::render_manager
virtual sg::render_manager & render_manager()=0
tools::sg::text_freetype::flush_line
void flush_line()
Definition: text_freetype:854
tools::sg::text_freetype::encoding_offset
static bool encoding_offset(FT_Face &a_face, unsigned short &a_offset)
Definition: text_freetype:2056
gluTessVertex
#define gluTessVertex
Definition: rename:13
tools::sg::vjust
vjust
Definition: enums:79
tools::sg::state::project_point
bool project_point(float &a_x, float &a_y, float &a_z, float &a_w) const
Definition: state:164
tools::sg::text_freetype::lines_t
std::vector< line_t > lines_t
Definition: text_freetype:2149
tools::to
std::vector< std::string > to(int a_argc, char **a_argv)
Definition: args:507
tools_vforit
#define tools_vforit(a__T, a__v, a__it)
Definition: forit:13
tools::vec3f
Definition: vec3f:13
tools::sg::render_action
Definition: render_action:24
tools::sg::text_freetype::m_encoding_offset
unsigned short m_encoding_offset
Definition: text_freetype:2130
tools::sg::gstos::get_gsto_id
unsigned int get_gsto_id(std::ostream &a_out, render_manager &a_mgr)
Definition: gstos:60
tools::sg::text_freetype::wndg_type
wndg_type
Definition: text_freetype:76
tools::sg::bottom
@ bottom
Definition: enums:80
tools::sg::render_action::begin_gsto
virtual void begin_gsto(gstoid)=0
VBO /////////////////////////////////////////////////////////.
tools::sg::middle
@ middle
Definition: enums:81
tools::sg::text_freetype
Definition: text_freetype:69
tools::sg::group::pick
virtual void pick(pick_action &a_action)
Definition: group:36
GLU_TESS_END_DATA
#define GLU_TESS_END_DATA
Definition: _glu:29
tools
inlined C code : ///////////////////////////////////
Definition: aida_ntuple:26
tools::sg::text_freetype::line_t
std::pair< size_t, size_t > line_t
outline lines //////////////////////////////////////
Definition: text_freetype:2148
tools::sg::render_action::draw_vertex_array_xy
virtual void draw_vertex_array_xy(gl::mode_t, size_t, const float *)=0
tools::sg::text_freetype::m_last_y
float m_last_y
Definition: text_freetype:2136
gluTessEndContour
GLUAPI void GLUAPIENTRY gluTessEndContour(GLUtesselator *tess)
Definition: glutess:486
GLU_TESS_BEGIN_DATA
#define GLU_TESS_BEGIN_DATA
Definition: _glu:27
gluDeleteTess
GLUAPI void GLUAPIENTRY gluDeleteTess(GLUtesselator *tess)
Definition: glutess:160
tools::sg::text_freetype::operator=
text_freetype & operator=(const text_freetype &a_from)
Definition: text_freetype:432
tools::colorf::auchar
uchar auchar() const
Definition: colorf:45
gluTessEndPolygon
GLUAPI void GLUAPIENTRY gluTessEndPolygon(GLUtesselator *tess)
Definition: glutess:493
tools::sg::text_freetype::begin_cbk
static void GLUAPIENTRY begin_cbk(GLUenum a_which, void *a_this)
Definition: text_freetype:1381
tools::sg::render_action::end_gsto
virtual void end_gsto()=0
enums
tools::sg::text_freetype::load_flags
static int load_flags()
Definition: text_freetype:1824
tools::sg::text_freetype::~text_freetype
virtual ~text_freetype()
Definition: text_freetype:412
tools::sg::text_freetype::wndg_cw
@ wndg_cw
Definition: text_freetype:78
tools::sg::text_freetype::m_xys
std::vector< float > m_xys
Definition: text_freetype:2144
tools::sg::base_text::strings
mf_string strings
Definition: base_text:29
tools::sg::text_freetype::lines
@ lines
Definition: text_freetype:568
tools::sg::text_freetype::y_advance
static bool y_advance(std::ostream &a_out, FT_Face &a_face, float a_height, float &a_adv)
Definition: text_freetype:1874
tools_sforcit
#define tools_sforcit(a__s, a__it)
Definition: forit:34
tools::sg::text_freetype::render
virtual void render(tools::sg::render_action &a_action)
Definition: text_freetype:182
tools::sg::text_freetype::combine_cbk
static void GLUAPIENTRY combine_cbk(double a_coords[3], void *[4], float[4], void **a_data_out, void *a_this)
Definition: text_freetype:1417
tools::sg::text_freetype::outline_cubic_to
static int outline_cubic_to(const FT_Vector *a_ctrl1, const FT_Vector *a_ctrl2, const FT_Vector *a_to, void *a_this)
Definition: text_freetype:1588
tools::sg::text_freetype::dump_unitext
void dump_unitext(std::ostream &a_out)
Definition: text_freetype:519
tools::sg::text_freetype::add_xy
void add_xy(float a_x, float a_y)
Definition: text_freetype:1713
tools::sg::text_freetype::triangles_t
std::vector< gl_triangle_t > triangles_t
Definition: text_freetype:2163
tools::sg::group::clear
void clear()
Definition: group:235
tools::gl::line_strip_to_lines_2to3
void line_strip_to_lines_2to3(size_t a_npt, const float *a_xyzs, float *&a_pxyzs)
Definition: glprims:399
tools::colorf::buchar
uchar buchar() const
Definition: colorf:44
tools::gl::cvt_2to3
void cvt_2to3(size_t a_npt, const float *a_xys, float *&a_xyzs)
Definition: glprims:39
tools::sg::text_freetype::bitmap_2_gl
bool bitmap_2_gl(std::ostream &a_out)
bitmap /////////////////////////////////////////////
Definition: text_freetype:1062
tools::sg::bsf::value
T & value()
Definition: bsf:98
tools::sg::action::out
std::ostream & out() const
Definition: action:51
tools::sg::text_freetype::m_trans_x
float m_trans_x
Definition: text_freetype:2138
tools::sg::text_freetype::triangle_t
std::pair< size_t, size_t > triangle_t
Definition: text_freetype:2161
tools::sg::bufpos
size_t bufpos
Definition: render_action:22
tools::line
Definition: line:13
gluTessCallback_GLU_TESS_BEGIN_DATA
void GLUAPIENTRY gluTessCallback_GLU_TESS_BEGIN_DATA(GLUtesselator *tess, void(GLUAPIENTRY *a_fn)(GLUenum, void *))
Definition: glutess:250
tools::sg::text_freetype::serrors::~serrors
virtual ~serrors()
Definition: text_freetype:1700
tools::sg::pick_action::add__primitive_xy
bool add__primitive_xy(sg::node &a_node, gl::mode_t a_mode, size_t a_floatn, const float *a_xys, bool a_stop=false, bool a_triangle_revert=false)
Definition: pick_action:336
tools::sg::text_freetype::update_sg
void update_sg(std::ostream &a_out, bool a_load_font)
Definition: text_freetype:600
tools::sg::text_freetype::m_bitmaps
tools::sg::group m_bitmaps
Definition: text_freetype:2170
tools::sg::state::m_color
colorf m_color
Definition: state:259
gluNewTess
GLUAPI GLUtesselator *GLUAPIENTRY gluNewTess(void)
Definition: glutess:59
tools::img::set
void set(unsigned int a_w, unsigned int a_h, unsigned int a_n, T *a_buffer, bool a_owner)
Definition: img:119
tools::sg::center
@ center
Definition: enums:75
tools_vforcit
#define tools_vforcit(a__T, a__v, a__it)
Definition: forit:7
tools::colorf::set_a
void set_a(float a_v)
Definition: colorf:40
tools::sg::base_tex::expand
sf< bool > expand
Definition: base_tex:30
tools::sg::text_freetype::bbox
virtual void bbox(tools::sg::bbox_action &a_action)
Definition: text_freetype:351
tools::sg::text_freetype::faces_and_lines
@ faces_and_lines
Definition: text_freetype:569
tools::sg::text_freetype::ascent
virtual float ascent(float a_height) const
Definition: text_freetype:450
tools::sg::states::state
const sg::state & state() const
Definition: states:76
tools::sg::font_filled
@ font_filled
Definition: enums:93
tools::sg::text_freetype::serrors::serrors
serrors()
Definition: text_freetype:1693
tools::sg::text_freetype::pick
virtual void pick(tools::sg::pick_action &a_action)
Definition: text_freetype:286
vec3d
tools::sg::text_freetype::char_2_bitmap
bool char_2_bitmap(std::ostream &a_out, unsigned int a_unichar)
Definition: text_freetype:1142
tools::sg::text_freetype::char_outline_2_gl
bool char_outline_2_gl(std::ostream &a_out, unsigned int a_unichar)
Definition: text_freetype:787
tools::sg::text_freetype::ascent
static bool ascent(std::ostream &a_out, FT_Face &a_face, float a_height, float &a_value)
Definition: text_freetype:1858
tools::sg::text_freetype::m_last_x
float m_last_x
Definition: text_freetype:2136
tools::sg::text_freetype::vertex_cbk
static void GLUAPIENTRY vertex_cbk(void *a_vertex, void *a_this)
Definition: text_freetype:1395
tools::sg::node::touched
virtual bool touched()
Definition: node:96
gluTessProperty
GLUAPI void GLUAPIENTRY gluTessProperty(GLUtesselator *tess, GLUenum which, GLUdouble data)
Definition: glutess:168
GLU_TESS_VERTEX_DATA
#define GLU_TESS_VERTEX_DATA
Definition: _glu:28
GLU_TESS_WINDING_RULE
#define GLU_TESS_WINDING_RULE
Definition: _glu:34
tools::colorf::ruchar
uchar ruchar() const
Definition: colorf:42
GLUenum
unsigned int GLUenum
Definition: _glu:14
tex_quadrilateral
tools::sg::base_freetype::unitext
mf_std_vec< unichar > unitext
Definition: base_freetype:24
tools::sg::text_freetype::outline_lines_2_gl
void outline_lines_2_gl(std::ostream &a_out)
Definition: text_freetype:709
tools::sg::text_freetype::update_what
update_what
outline lines //////////////////////////////////////
Definition: text_freetype:566
gluTessCallback_GLU_TESS_END_DATA
void GLUAPIENTRY gluTessCallback_GLU_TESS_END_DATA(GLUtesselator *tess, void(GLUAPIENTRY *a_fn)(void *))
Definition: glutess:254
tools::sg::node::reset_touched
virtual void reset_touched()
Definition: node:102
tools::sg::text_freetype::get_bounds
virtual void get_bounds(float a_height, float &a_mn_x, float &a_mn_y, float &a_mn_z, float &a_mx_x, float &a_mx_y, float &a_mx_z) const
Definition: text_freetype:489
bbox_action