4 #ifndef tools_sg_text_freetype
5 #define tools_sg_text_freetype
25 #include "../glutess/glutess"
30 #ifndef TOOLS_USE_OUREX_FREETYPE
33 #include <ourex_ft2build.h>
59 #include FT_FREETYPE_H
83 std::vector<float> gsto_data;
87 size_t pos = item.first;
88 size_t num = item.second;
91 a_out <<
"tools::sg::text_freetype::create_gsto :"
92 <<
" strange line with " << num <<
" points."
97 const float* data = tools::vec_data<float>(
m_xys)+pos;
101 size_t nsegs = num-1;
103 size_t ngsto = nsegs*2*3;
104 size_t sz = gsto_data.size();
105 gsto_data.resize(sz+ngsto);
106 float* pxyz = tools::vec_data<float>(gsto_data)+sz;
114 const std::pair<GLUenum,triangle_t>& item = *it;
115 size_t pos = item.second.first;
116 size_t num = item.second.second;
119 a_out <<
"tools::sg::text_freetype::create_gsto :"
120 <<
" strange triangle primitive with " << num <<
" points."
121 <<
" Primitive kind is " << (*it).first <<
"."
126 const float* data = tools::vec_data<float>(
m_xys)+pos;
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;
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;
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;
162 a_out <<
"tools::sg::text_freetype::create_gsto :"
163 <<
" unknown triangle primitive kind " << (*it).first <<
"."
171 if(gsto_data.empty()) {
185 if(
touched()||_color_touched||_char_height_touched) {
234 size_t pos = item.first;
235 size_t num = item.second;
241 const float* data = tools::vec_data<float>(
m_xys)+pos;
252 const std::pair<GLUenum,triangle_t>& item = *it;
253 size_t pos = item.second.first;
254 size_t num = item.second.second;
260 const float* data = tools::vec_data<float>(
m_xys)+pos;
276 _state.
m_color = tools::colorf_white();
288 if(
touched()||_char_height_touched) {
327 size_t pos = item.first;
328 size_t num = item.second;
329 const float* data = tools::vec_data<float>(
m_xys)+pos;
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;
353 if(
touched()||_char_height_touched) {
360 size_t num = item.second;
361 const float* data = tools::vec_data<float>(
m_xys)+item.first;
364 float* pos = (
float*)data;
365 for(
size_t index=0;index<num;index++) {
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;
383 float* pos = (
float*)data;
384 for(
size_t index=0;index<num;index++) {
434 if(&a_from==
this)
return *
this;
450 virtual float ascent(
float a_height)
const {
456 #ifdef TOOLS_DONE_FACE
469 #ifdef TOOLS_DONE_FACE
482 #ifdef TOOLS_DONE_FACE
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 {
500 #ifdef TOOLS_DONE_FACE
506 virtual bool truncate(
const std::string& a_string,
float a_height,
float a_cut_width,std::string& a_out)
const {
511 if(!
truncate(out,
self().
m_face,a_height,a_string,a_cut_width,a_out))
return false;
512 #ifdef TOOLS_DONE_FACE
521 a_out <<
"unitext size : " <<
unitext.
values().size() << std::endl;
524 a_out <<
"beg line :" << std::endl;
527 a_out << ((
unsigned int)*it) << std::endl;
529 a_out <<
"end line." << std::endl;
535 FT_Error error = ::FT_Init_FreeType(&
m_library);
590 float screen_height = ymx-ymn;
591 if(a_state.
m_wh) screen_height *= a_state.
m_wh;
else screen_height = 100;
613 a_out <<
"tools::sg::text_freetype::update_sg :"
614 <<
" encoding_offset failed."
646 float mn_x,mn_y,mn_z;
647 float mx_x,mx_y,mx_z;
649 float szy = mx_y - mn_y;
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;
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;
668 std::vector<tools::vec3f>& vcs = (*itqs)->corners.values();
669 for(
size_t i=0;i<4;i++) vcs[i][1] -= 0.5f * szy;
673 float mn_x,mn_y,mn_z;
674 float mx_x,mx_y,mx_z;
676 float szy = mx_y - mn_y;
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;
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;
695 std::vector<tools::vec3f>& vcs = (*itqs)->corners.values();
696 for(
size_t i=0;i<4;i++) vcs[i][1] -= szy;
703 #ifdef TOOLS_DONE_FACE
711 FT_Pos face_height =
m_face->size->metrics.height;
718 const std::string&
line = *vit;
726 yline += -float(face_height)*
m_scale;
731 for(
size_t index=ibeg;index<num;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;
740 for(
size_t index=ibeg;index<num;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;
761 yline += -float(face_height)*
m_scale;
766 for(
size_t index=ibeg;index<num;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;
775 for(
size_t index=ibeg;index<num;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;
788 FT_ULong charcode = a_unichar;
789 FT_UInt glyph_index = ::FT_Get_Char_Index(
m_face,charcode);
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
802 a_out <<
"tools::sg::text_freetype::char_outline_2_gl :"
803 <<
" for character " << a_unichar
804 <<
",FT_Load_Glyph : error : " <<
serror(error)
812 if(
m_face->glyph->format!=FT_GLYPH_FORMAT_OUTLINE) {
813 a_out <<
"tools::sg::text_freetype::char_outline_2_gl :"
815 <<
" and for character " << a_unichar
816 <<
" glyph not at format outline."
823 FT_Outline outline =
m_face->glyph->outline;
825 {FT_Error error = ::FT_Outline_Decompose(&outline,&
m_funcs,
this);
827 a_out <<
"tools::sg::text_freetype::char_outline_2_gl :"
828 <<
" for character " << a_unichar
829 <<
",FT_Outline_Decompose : error : " <<
serror(error)
845 a_out <<
"tools::sg::text_freetype::char_outline_2_gl :"
846 <<
" for character " << a_unichar <<
", winding anomaly."
867 FT_Pos face_height =
m_face->size->metrics.height;
871 #ifdef TOOLS_USE_NATIVE_GLUTESS
896 const std::string&
line = *vit;
908 yline += -float(face_height)*
m_scale;
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;
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;
946 yline += -float(face_height)*
m_scale;
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;
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;
982 FT_ULong charcode = a_unichar;
983 FT_UInt glyph_index = ::FT_Get_Char_Index(
m_face,charcode);
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
996 a_out <<
"tools::sg::text_freetype::char_triangles_2_gl :"
997 <<
" for character " << a_unichar
998 <<
",FT_Load_Glyph : error : " <<
serror(error)
1006 if(
m_face->glyph->format!=FT_GLYPH_FORMAT_OUTLINE) {
1007 a_out <<
"tools::sg::text_freetype::char_triangles_2_gl :"
1009 <<
" and for character " << a_unichar
1010 <<
" glyph not at format outline."
1017 FT_Outline outline =
m_face->glyph->outline;
1026 {FT_Error error = ::FT_Outline_Decompose(&outline,&
m_funcs,
this);
1028 a_out <<
"tools::sg::text_freetype::char_triangles_2_gl :"
1029 <<
" for character " << a_unichar
1030 <<
",FT_Outline_Decompose : error : " <<
serror(error)
1051 a_out <<
"tools::sg::text_freetype::char_triangles_2_gl :"
1052 <<
" for character " << a_unichar <<
", winding anomaly."
1069 FT_Error error = ::FT_Set_Char_Size(
m_face,wchar,
hchar,hres,vres);
1071 a_out <<
"tools::sg::text_freetype::bitmap_2_gl :"
1072 <<
" FT_Set_Char_Size : error : " <<
serror(error) <<
"."
1080 FT_Pos face_height =
m_face->size->metrics.height;
1085 const std::string&
line = *vit;
1089 size_t ibeg =
m_tqs.size();
1093 yline += -float(face_height)*
m_scale;
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;
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;
1117 size_t ibeg =
m_tqs.size();
1121 yline += -float(face_height)*
m_scale;
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;
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;
1149 FT_ULong charcode = a_unichar;
1150 FT_UInt glyph_index = ::FT_Get_Char_Index(
m_face,charcode);
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
1163 a_out <<
"tools::sg::text_freetype::char_2_bitmap :"
1164 <<
" for character " << a_unichar
1165 <<
",FT_Load_Glyph : error : " <<
serror(error)
1173 {FT_Error error = ::FT_Get_Glyph(
m_face->glyph,&glyph);
1175 a_out <<
"tools::sg::text_freetype::char_2_bitmap :"
1177 <<
" and for character " << a_unichar
1178 <<
" could not get glyph."
1185 bool smoothing =
true;
1186 {FT_Error error = ::FT_Glyph_To_Bitmap(&glyph,(smoothing?ft_render_mode_normal:ft_render_mode_mono),0,1);
1188 a_out <<
"tools::sg::text_freetype::char_2_bitmap :"
1190 <<
" and for character " << a_unichar
1191 <<
" could not get glyph bitmap."
1193 ::FT_Done_Glyph(glyph);
1210 FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
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 :"
1219 <<
" and for character " << a_unichar
1220 <<
" not a mono or grays pixmap."
1222 ::FT_Done_Glyph(glyph);
1228 if(bitmap->bitmap.pitch<0) {
1229 a_out <<
"tools::sg::text_freetype::char_2_bitmap :"
1231 <<
" and for character " << a_unichar
1232 <<
" negative bitmap pitch."
1234 ::FT_Done_Glyph(glyph);
1240 unsigned int img_w = 0;
1241 unsigned int img_h = 0;
1242 unsigned int img_bpp = 4;
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;
1249 img_h = bitmap->bitmap.rows;
1252 img_w = (bitmap->bitmap.width+7)/8;
1253 img_sz = img_w * img_h;
1255 ::FT_Done_Glyph(glyph);
1261 if(
int(bitmap->bitmap.width)!=bitmap->bitmap.pitch) {
1262 a_out <<
"tools::sg::text_freetype::char_2_bitmap :"
1264 <<
" and for character " << a_unichar
1265 <<
"bitmap pitch (" << bitmap->bitmap.pitch <<
") != width (" << bitmap->bitmap.width <<
")."
1267 ::FT_Done_Glyph(glyph);
1272 img_w = bitmap->bitmap.width;
1273 img_h = bitmap->bitmap.rows;
1274 img_sz = img_w * img_h * img_bpp;
1283 a_out <<
"tools::sg::text_freetype::char_2_bitmap :"
1285 <<
" and for character " << a_unichar
1286 <<
", can't alloc bitmap buffer for character."
1288 ::FT_Done_Glyph(glyph);
1296 back_color.
set_a(0);
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;
1312 FT_Glyph_Get_CBox(glyph,ft_glyph_bbox_pixels,&_bbox);
1317 std::vector<tools::vec3f> vcs;
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;
1333 _node->
img.
value().
set(img_w,img_h,img_bpp,img_buffer,
true);
1338 _node->
corners.set_values(vcs);
1341 m_tqs.push_back(_node);
1374 ::FT_Done_Glyph(glyph);
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
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]
1405 self.
add_xy(
float(vertex[0]),float(vertex[1]));
1410 size_t num = (
self.m_xys.size()-
self.m_pos)/2;
1413 self.m_triangles.push_back(std::pair<GLUenum,triangle_t>(
self.
m_mode,t));
1455 self.
set_g(gx,gy,
float(a_to->x),float(a_to->y));
1460 self.m_contour_open =
false;
1464 self.m_contour_open =
true;
1466 {
double* v =
self.add_glutess_vec3d(gx,gy,0);
1474 self.m_last_x = float(a_to->x);
1475 self.m_last_y = float(a_to->y);
1488 self.
set_g(gx,gy,
float(a_to->x),float(a_to->y));
1491 double* v =
self.add_glutess_vec3d(gx,gy,0);
1497 self.m_last_x = float(a_to->x);
1498 self.m_last_y = float(a_to->y);
1514 float ctrlx = float(a_ctrl->x);
1515 float ctrly = float(a_ctrl->y);
1517 float fromx =
self.m_last_x;
1518 float fromy =
self.m_last_y;
1520 float tox = float(a_to->x);
1521 float toy = float(a_to->y);
1530 float bx = fromx - 2 * ctrlx + tox;
1531 float by = fromy - 2 * ctrly + toy;
1533 float cx = -2 * fromx + 2 * ctrlx;
1534 float cy = -2 * fromy + 2 * ctrly;
1536 float dfx = cx *
self.m_delta + bx *
self.m_delta2;
1537 float dfy = cy *
self.m_delta + by *
self.m_delta2;
1539 float df2x = 2 * bx *
self.m_delta2;
1540 float df2y = 2 * by *
self.m_delta2;
1550 size_t num =
self.m_steps - 1;
1551 for(
size_t i=0;i<num;i++) {
1555 self.set_g(gx,gy,fromx,fromy);
1558 double* v =
self.add_glutess_vec3d(gx,gy,0);
1569 self.set_g(gx,gy,tox,toy);
1572 double* v =
self.add_glutess_vec3d(gx,gy,0);
1579 self.m_last_x = tox;
1580 self.m_last_y = toy;
1584 void set_g(
float& a_gx,
float& a_gy,
float a_x,
float a_y)
const {
1588 static int outline_cubic_to(
const FT_Vector* a_ctrl1,
const FT_Vector* a_ctrl2,
const FT_Vector* a_to,
void* a_this){
1602 float ctrl1x = float(a_ctrl1->x);
1603 float ctrl1y = float(a_ctrl1->y);
1605 float ctrl2x = float(a_ctrl2->x);
1606 float ctrl2y = float(a_ctrl2->y);
1608 float fromx =
self.m_last_x;
1609 float fromy =
self.m_last_y;
1611 float tox = float(a_to->x);
1612 float toy = float(a_to->y);
1624 float ax = -fromx + 3 * ctrl1x - 3 * ctrl2x + tox;
1625 float ay = -fromy + 3 * ctrl1y - 3 * ctrl2y + toy;
1627 float bx = 3 * fromx - 6 * ctrl1x + 3 * ctrl2x;
1628 float by = 3 * fromy - 6 * ctrl1y + 3 * ctrl2y;
1630 float cx = -3 * fromx + 3 * ctrl1x;
1631 float cy = -3 * fromy + 3 * ctrl1y;
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;
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;
1639 float df3x = 6 * ax *
self.m_delta3;
1640 float df3y = 6 * ay *
self.m_delta3;
1649 size_t num =
self.m_steps - 1;
1650 for(
size_t i=0;i<num;i++) {
1654 self.set_g(gx,gy,fromx,fromy);
1657 double* v =
self.add_glutess_vec3d(gx,gy,0);
1671 self.set_g(gx,gy,tox,toy);
1674 double* v =
self.add_glutess_vec3d(gx,gy,0);
1681 self.m_last_x = tox;
1682 self.m_last_y = toy;
1690 class serrors :
public std::map<int,std::string> {
1691 typedef std::map<int,std::string> parent;
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
1707 std::map<int,std::string>::const_iterator it = errs.find(a_FT_Error);
1708 if(it!=errs.end())
return (*it).second;
1714 m_xys.push_back(a_x);
1715 m_xys.push_back(a_y);
1762 a_out <<
"tools::sg::text_freetype::load_face :"
1763 <<
" freetype library not initialized."
1769 a_out <<
"tools::sg::text_freetype::load_face :"
1779 a_out <<
"tools::sg::text_freetype::load_face :"
1780 <<
" no font file given."
1791 a_out <<
"tools::sg::text_freetype::load_face :"
1792 <<
" font file not found for font "
1800 a_out <<
"tools::sg::text_freetype::load_face :"
1801 <<
" load font file " <<
tools::sout(file) <<
" ..."
1807 a_out <<
"tools::sg::text_freetype::load_face :"
1808 <<
" FT_New_Face : error : " <<
serror(error) <<
"."
1816 a_out <<
"tools::sg::text_freetype::load_face :"
1825 return FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
1830 static bool set_char_size(std::ostream& a_out,FT_Face& a_face,
float a_height,
float& a_scale) {
1839 FT_F26Dot6 wchar = 1000*64;
1840 FT_F26Dot6
hchar = 1000*64;
1844 FT_Error error = ::FT_Set_Char_Size(a_face,wchar,
hchar,hres,vres);
1846 a_out <<
"tools::sg::text_freetype::set_char_size :"
1847 <<
" FT_Set_Char_Size : error : " <<
serror(error) <<
"."
1849 ::FT_Done_Face(a_face);
1854 a_scale = a_height/float(wchar);
1858 static bool ascent(std::ostream& a_out,FT_Face& a_face,
float a_height,
float& a_value) {
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;
1862 a_value = float(
ascent) * scale;
1866 static bool descent(std::ostream& a_out,FT_Face& a_face,
float a_height,
float& a_value) {
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;
1870 a_value = -(float(
descent) * scale);
1874 static bool y_advance(std::ostream& a_out,FT_Face& a_face,
float a_height,
float& a_adv) {
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;
1878 a_adv = float(face_height)*scale;
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) {
1887 if(!
set_char_size(a_out,a_face,a_height,scale))
return false;
1891 unsigned short offset;
1895 FT_ULong charcode = *it + offset;
1896 FT_UInt glyph_index = ::FT_Get_Char_Index(a_face,charcode);
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
1905 ::FT_Done_Face(a_face);
1910 {FT_Error error = ::FT_Load_Glyph(a_face,glyph_index,
load_flags());
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)
1919 ::FT_Done_Face(a_face);
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;
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){
1940 if(a_text.empty())
return true;
1943 if(!
set_char_size(a_out,a_face,a_height,scale))
return false;
1947 unsigned short offset;
1951 const std::string&
line = *vit;
1955 FT_ULong charcode = *it + offset;
1956 FT_UInt glyph_index = ::FT_Get_Char_Index(a_face,charcode);
1958 if((FT_Long)glyph_index>=a_face->num_glyphs) {
1959 ::FT_Done_Face(a_face);
1964 {FT_Error error = ::FT_Load_Glyph(a_face,glyph_index,
load_flags());
1966 ::FT_Done_Face(a_face);
1972 float advance = float(a_face->glyph->advance.x)*scale;
1976 xmx = tools::mx<float>(xmx,width);
1979 FT_Pos
ascent = a_face->size->metrics.ascender;
1980 FT_Pos
descent = a_face->size->metrics.descender;
1981 FT_Pos face_height = a_face->size->metrics.height;
1983 float ymn = -float(face_height)*scale*(a_text.size()-1)
1990 a_mx_y = float(
ascent)*scale;
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){
2002 if(a_text.empty())
return true;
2005 if(!
set_char_size(a_out,a_face,a_height,scale))
return false;
2015 FT_ULong charcode = *it;
2016 FT_UInt glyph_index = ::FT_Get_Char_Index(a_face,charcode);
2018 if((FT_Long)glyph_index>=a_face->num_glyphs) {
2019 ::FT_Done_Face(a_face);
2024 {FT_Error error = ::FT_Load_Glyph(a_face,glyph_index,
load_flags());
2026 ::FT_Done_Face(a_face);
2032 float advance = float(a_face->glyph->advance.x)*scale;
2036 xmx = tools::mx<float>(xmx,width);
2039 FT_Pos
ascent = a_face->size->metrics.ascender;
2040 FT_Pos
descent = a_face->size->metrics.descender;
2041 FT_Pos face_height = a_face->size->metrics.height;
2043 float ymn = -float(face_height)*scale*(a_text.size()-1)
2050 a_mx_y = float(
ascent)*scale;
2082 FT_Int n = a_face->num_charmaps;
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;
2095 if ( (platform == 3 && encoding == 1 ) ||
2096 (platform == 3 && encoding == 0 ) ||
2098 (platform == 0 && encoding == 0 ) ) {
2099 FT_Error error = FT_Set_Charmap(a_face,charmap);
2101 ::FT_Done_Face(a_face);
2107 if (platform == 3 && encoding == 0 ) a_offset = 0xF000;
2121 ::FT_Done_Face(a_face);
2171 std::vector<tools::sg::tex_quadrilateral*>
m_tqs;