// ============================================================== // This file is part of the MegaGlest Shared Library (www.megaglest.org) // // Copyright (C) 2011 Mark Vejvoda and others // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published // by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== #ifdef USE_FTGL //#include "gettext.h" #include "font_textFTGL.h" #include "opengl.h" #include #include #include #include "platform_common.h" #include "util.h" using namespace std; using namespace Shared::Util; using namespace Shared::PlatformCommon; namespace Shared { namespace Graphics { namespace Gl { string TextFTGL::langHeightText = "yW"; int TextFTGL::faceResolution = 72; //==================================================================== TextFTGL::TextFTGL(FontTextHandlerType type) : Text(type) { //throw megaglest_runtime_error("FTGL!"); //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",0); //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/arphic/uming.ttc",0); // Chinese //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/arphic/ukai.ttc",0); // Chinese //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/ttf-sil-doulos/DoulosSILR.ttf",0); // Russian / Cyrillic //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/ttf-sil-charis/CharisSILR.ttf",0); // Russian / Cyrillic //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-R.ttf",0); // Russian / Cyrillic //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/takao/TakaoPGothic.ttf",0); // Japanese //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/ttf-sil-scheherazade/ScheherazadeRegOT.ttf",0); // Arabic //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/linux-libertine/LinLibertine_Re.ttf",0); // Hebrew //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/unifont/unifont.ttf",0); // Czech? //setenv("MEGAGLEST_FONT","/usr/share/fonts/truetype/ttf-liberation/LiberationSans-Regular.ttf",0); // Czech? fontFile = findFont(); //ftFont = new FTBufferFont(fontFile); //ftFont = new FTGLPixmapFont(fontFile); //ftFont = new FTGLExtrdFont(fontFile); //ftFont = new FTGLPolygonFont("/usr/share/fonts/truetype/arphic/uming.ttc"); //ftFont = new FTGLPixmapFont("/usr/share/fonts/truetype/arphic/uming.ttc"); if(type == ftht_2D) { ftFont = new FTGLPixmapFont(fontFile); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("2D font [%s]\n",fontFile); } else if(type == ftht_3D) { ftFont = new FTGLTextureFont(fontFile); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("3D font [%s]\n",fontFile); } else { throw megaglest_runtime_error("font render type not set to a known value!"); } if(ftFont->Error()) { string fontFileName = (fontFile != NULL ? fontFile : "n/a"); printf("FTGL: error loading font: %s\n", fontFileName.c_str()); delete ftFont; ftFont = NULL; if(fontFile != NULL) free((void*)fontFile); fontFile = NULL; throw megaglest_runtime_error(string("FTGL: error loading font: ") + fontFileName); } free((void*)fontFile); fontFile = NULL; const unsigned int defSize = 24; ftFont->FaceSize(defSize,TextFTGL::faceResolution); GLenum error = glGetError(); if(error != GL_NO_ERROR) { printf("\n[%s::%s] Line %d Error = %d [%s] for size = %u res = %d\n",__FILE__,__FUNCTION__,__LINE__,error,gluErrorString(error),defSize,TextFTGL::faceResolution); fflush(stdout); } if(ftFont->Error()) { char szBuf[8096]=""; snprintf(szBuf,8096,"FTGL: error setting face size, #%d",ftFont->Error()); throw megaglest_runtime_error(szBuf); } //ftFont->UseDisplayList(false); //ftFont->CharMap(ft_encoding_gb2312); //ftFont->CharMap(ft_encoding_big5); if(ftFont->CharMap(ft_encoding_unicode) == false) { throw megaglest_runtime_error("FTGL: error setting encoding"); } if(ftFont->Error()) { char szBuf[8096]=""; snprintf(szBuf,8096,"FTGL: error setting encoding, #%d",ftFont->Error()); throw megaglest_runtime_error(szBuf); } } TextFTGL::~TextFTGL() { cleanupFont(); } void TextFTGL::cleanupFont() { delete ftFont; ftFont = NULL; if(fontFile) { free((void*)fontFile); } fontFile = NULL; } void TextFTGL::init(string fontName, string fontFamilyName, int fontSize) { cleanupFont(); fontFile = findFont(fontName.c_str(),fontFamilyName.c_str()); //ftFont = new FTBufferFont(fontFile); //ftFont = new FTGLPixmapFont(fontFile); //ftFont = new FTGLExtrdFont(fontFile); //ftFont = new FTGLPolygonFont("/usr/share/fonts/truetype/arphic/uming.ttc"); //ftFont = new FTGLPixmapFont("/usr/share/fonts/truetype/arphic/uming.ttc"); if(type == ftht_2D) { ftFont = new FTGLPixmapFont(fontFile); //printf("2D font [%s]\n",fontFile); } else if(type == ftht_3D) { ftFont = new FTGLTextureFont(fontFile); //ftFont = new FTBufferFont(fontFile); //ftFont = new FTGLExtrdFont(fontFile); //ftFont = new FTGLPolygonFont("/usr/share/fonts/truetype/arphic/uming.ttc"); //printf("3D font [%s]\n",fontFile); } else { throw megaglest_runtime_error("font render type not set to a known value!"); } if(ftFont->Error()) { printf("FTGL: error loading font: %s\n", fontFile); delete ftFont; ftFont = NULL; if(fontFile) { free((void*)fontFile); } fontFile = NULL; throw megaglest_runtime_error("FTGL: error loading font"); } free((void*)fontFile); fontFile = NULL; if(fontSize <= 0) { fontSize = 24; } ftFont->FaceSize(fontSize,TextFTGL::faceResolution); GLenum error = glGetError(); if(error != GL_NO_ERROR) { printf("\n[%s::%s] Line %d Error = %d [%s] for size = %d res = %d\n",__FILE__,__FUNCTION__,__LINE__,error,gluErrorString(error),fontSize,TextFTGL::faceResolution); fflush(stdout); } if(ftFont->Error()) { char szBuf[8096]=""; snprintf(szBuf,8096,"FTGL: error setting face size, #%d",ftFont->Error()); throw megaglest_runtime_error(szBuf); } //ftFont->UseDisplayList(false); //ftFont->CharMap(ft_encoding_gb2312); //ftFont->CharMap(ft_encoding_big5); if(ftFont->CharMap(ft_encoding_unicode) == false) { throw megaglest_runtime_error("FTGL: error setting encoding"); } if(ftFont->Error()) { char szBuf[8096]=""; snprintf(szBuf,8096,"FTGL: error setting encoding, #%d",ftFont->Error()); throw megaglest_runtime_error(szBuf); } // Create a string containing common characters // and preload the chars without rendering them. string preloadText = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-=!@#$%^&*()_+:\"{}[]/?.,<>\\';"; ftFont->Advance(preloadText.c_str()); error = glGetError(); if(error != GL_NO_ERROR) { printf("\n[%s::%s] Line %d Error = %d [%s] for text [%s]\n",__FILE__,__FUNCTION__,__LINE__,error,gluErrorString(error),preloadText.c_str()); fflush(stdout); } if(ftFont->Error()) { char szBuf[8096]=""; snprintf(szBuf,8096,"FTGL: error advancing(a), #%d",ftFont->Error()); throw megaglest_runtime_error(szBuf); } } void TextFTGL::SetFaceSize(int value) { ftFont->FaceSize(value,TextFTGL::faceResolution); GLenum error = glGetError(); if(error != GL_NO_ERROR) { printf("\n[%s::%s] Line %d Error = %d [%s] for facesize = %d\n",__FILE__,__FUNCTION__,__LINE__,error,gluErrorString(error),value); fflush(stdout); } if(ftFont->Error()) { char szBuf[8096]=""; snprintf(szBuf,8096,"FTGL: error setting face size, #%d",ftFont->Error()); throw megaglest_runtime_error(szBuf); } } int TextFTGL::GetFaceSize() { return ftFont->FaceSize(); } void TextFTGL::Render(const char* str, const int len) { //printf("Render TextFTGL\n"); /* FTGL renders the whole string when len == 0 but we don't want any text rendered then. */ if(len != 0) { //printf("FTGL Render [%s] facesize = %d\n",str,ftFont->FaceSize()); assertGl(); ftFont->Render(str, len); //assertGl(); GLenum error = glGetError(); if(error != GL_NO_ERROR) { printf("\n[%s::%s] Line %d Error = %d [%s] for text [%s]\n",__FILE__,__FUNCTION__,__LINE__,error,gluErrorString(error),str); fflush(stdout); } if(ftFont->Error()) { char szBuf[8096]=""; snprintf(szBuf,8096,"FTGL: error trying to render, #%d",ftFont->Error()); throw megaglest_runtime_error(szBuf); } } } float TextFTGL::Advance(const char* str, const int len) { float result = ftFont->Advance(str, len); GLenum error = glGetError(); if(error != GL_NO_ERROR) { printf("\n[%s::%s] Line %d Error = %d [%s] for text [%s]\n",__FILE__,__FUNCTION__,__LINE__,error,gluErrorString(error),str); fflush(stdout); } if(ftFont->Error()) { char szBuf[8096]=""; snprintf(szBuf,8096,"FTGL: error trying to advance(b), #%d",ftFont->Error()); throw megaglest_runtime_error(szBuf); } return result; //FTBBox box = ftFont->BBox(str); //float urx = box.Upper().X(); //float llx = box.Lower().X(); //float llx, lly, llz, urx, ury, urz; //ftFont->BBox(str, llx, lly, llz, urx, ury, urz); //Short_t halign = fTextAlign/10; //Short_t valign = fTextAlign - 10*halign; //Float_t dx = 0, dy = 0; // switch (halign) { // case 1 : dx = 0 ; break; // case 2 : dx = -urx/2; break; // case 3 : dx = -urx ; break; // } // switch (valign) { // case 1 : dy = 0 ; break; // case 2 : dy = -ury/2; break; // case 3 : dy = -ury ; break; // } //printf("For str [%s] advance = %f, urx = %f, llx = %f\n",str, ftFont->Advance(str, len),urx,llx); //return urx; } float TextFTGL::LineHeight(const char* str, const int len) { //FTBBox box = ftFont->BBox(str); //printf("String [%s] lineheight = %f upper_y = %f lower_y = %f\n",str,ftFont->LineHeight(),box.Upper().Y(),box.Lower().Y()); //printf("ftFont->Ascender():%f ftFont->Descender()*-1 = %f ftFont->LineHeight() = %f\n",ftFont->Ascender(),ftFont->Descender()*-1 , ftFont->LineHeight()); //return ftFont->Ascender() + ftFont->Descender()*-1 - ftFont->LineHeight(); //return ftFont->LineHeight(); //static float result = -1000; float result = -1000; if(result == -1000) { FTBBox box = ftFont->BBox(TextFTGL::langHeightText.c_str()); GLenum error = glGetError(); if(error != GL_NO_ERROR) { printf("\n[%s::%s] Line %d Error = %d [%s] for text [%s]\n",__FILE__,__FUNCTION__,__LINE__,error,gluErrorString(error),str); fflush(stdout); } result = box.Upper().Yf()- box.Lower().Yf(); if(result == 0) { result = ftFont->LineHeight(); GLenum error = glGetError(); if(error != GL_NO_ERROR) { printf("\n[%s::%s] Line %d Error = %d [%s] for text [%s]\n",__FILE__,__FUNCTION__,__LINE__,error,gluErrorString(error),str); fflush(stdout); } } //printf("ftFont->BBox(''yW'')%f\n",result); } // else { // FTBBox box = ftFont->BBox(TextFTGL::langHeightText.c_str()); // // GLenum error = glGetError(); // if(error != GL_NO_ERROR) { // printf("\n[%s::%s] Line %d Error = %d [%s] for text [%s]\n",__FILE__,__FUNCTION__,__LINE__,error,gluErrorString(error),str); // fflush(stdout); // } // // int newresult = box.Upper().Y()- box.Lower().Y(); // if(newresult == 0) { // newresult = ftFont->LineHeight(); // // GLenum error = glGetError(); // if(error != GL_NO_ERROR) { // printf("\n[%s::%s] Line %d Error = %d [%s] for text [%s]\n",__FILE__,__FUNCTION__,__LINE__,error,gluErrorString(error),str); // fflush(stdout); // } // } // // printf("Height for [%s] result [%d] [%d]\n",str,result,newresult); // } if(ftFont->Error()) { char szBuf[8096]=""; snprintf(szBuf,8096,"FTGL: error trying to get lineheight, #%d",ftFont->Error()); throw megaglest_runtime_error(szBuf); } return result; // printf("For str [%s] LineHeight = %f, result = %f\n",str, ftFont->LineHeight(),result); // return result; //float urx = box.Upper().X(); //float llx = box.Lower().X(); //float llx, lly, llz, urx, ury, urz; //ftFont->BBox(str, llx, lly, llz, urx, ury, urz); //return ury - lly; //Short_t halign = fTextAlign/10; //Short_t valign = fTextAlign - 10*halign; //Float_t dx = 0, dy = 0; // switch (halign) { // case 1 : dx = 0 ; break; // case 2 : dx = -urx/2; break; // case 3 : dx = -urx ; break; // } // switch (valign) { // case 1 : dy = 0 ; break; // case 2 : dy = -ury/2; break; // case 3 : dy = -ury ; break; // } //printf("For str [%s] advance = %f, urx = %f, llx = %f\n",str, ftFont->Advance(str, len),urx,llx); //return urx; } float TextFTGL::LineHeight(const wchar_t* str, const int len) { static float result = -1000; if(result == -1000) { FTBBox box = ftFont->BBox(TextFTGL::langHeightText.c_str()); result = box.Upper().Yf()- box.Lower().Yf(); if(result == 0) { result = ftFont->LineHeight(); } //printf("ftFont->BBox(''yW'')%f\n",result); } if(ftFont->Error()) { char szBuf[8096]=""; snprintf(szBuf,8096,"FTGL: error trying to get lineheight, #%d",ftFont->Error()); throw megaglest_runtime_error(szBuf); } return result; } void TextFTGL::Render(const wchar_t* str, const int len) { /* FTGL renders the whole string when len == 0 but we don't want any text rendered then. */ if(len != 0) { ftFont->Render(str, len); if(ftFont->Error()) { char szBuf[8096]=""; snprintf(szBuf,8096,"FTGL: error trying to render, #%d",ftFont->Error()); throw megaglest_runtime_error(szBuf); } } } float TextFTGL::Advance(const wchar_t* str, const int len) { float result = ftFont->Advance(str, len); if(ftFont->Error()) { char szBuf[8096]=""; snprintf(szBuf,8096,"FTGL: error trying to advance(c), #%d",ftFont->Error()); throw megaglest_runtime_error(szBuf); } return result; } }}}//end namespace #endif // USE_FTGL