/* ************************************************************************* * SDL-Ball - DX-Ball/Breakout remake with openGL and SDL for Linux Copyright (C) 2008 Jimmy Christensen ( dusted at dusted dot dk ) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . * ************************************************************************* */ #define FONT_MENU 0 #define FONT_ANNOUNCE_GOOD 1 #define FONT_ANNOUNCE_BAD 2 #define FONT_HIGHSCORE 3 #define FONT_MENUHIGHSCORE 4 #define FONT_INTROHIGHSCORE 5 #define FONT_INTRODESCRIPTION 6 #define FONT_NUM 7 struct glCharInfo_struct { GLfloat Xa,Ya,Xb,Yb, width; }; struct glFontInfo_struct { GLuint tex; GLfloat height; struct glCharInfo_struct ch[255]; }; class glTextClass { private: void genFontTex(string TTFfontName, int fontSize, int font); struct glFontInfo_struct fontInfo[FONT_NUM]; public: GLfloat getHeight(int font); void write(string text, int font, bool center, GLfloat scale, GLfloat x, GLfloat y); glTextClass(); }; GLfloat glTextClass::getHeight(int font) { return(fontInfo[font].height*2.0); } glTextClass::glTextClass() { TTF_Init(); //Parse font-description file ifstream f; string line,set,val,tempName; f.open( useTheme("/font/fonts.txt",setting.gfxTheme).data() ); if(f.is_open()) { while(!f.eof()) { getline(f, line); if(line.find('=') != string::npos) { set=line.substr(0,line.find('=')); val=line.substr(line.find('=')+1); if(set=="menufile") { tempName=val; } else if(set=="menusize") { genFontTex(tempName, atoi(val.data()), FONT_MENU); } else if(set=="announcegoodfile") { tempName=val; } else if(set=="announcegoodsize") { genFontTex(tempName, atoi(val.data()), FONT_ANNOUNCE_GOOD); } else if(set=="announcebadfile") { tempName=val; } else if(set=="announcebadsize") { genFontTex(tempName, atoi(val.data()), FONT_ANNOUNCE_BAD); } else if(set=="highscorefile") { tempName=val; } else if(set=="highscoresize") { genFontTex(tempName, atoi(val.data()), FONT_HIGHSCORE); } else if(set=="menuhighscorefile") { tempName=val; } else if(set=="menuhighscoresize") { genFontTex(tempName, atoi(val.data()), FONT_MENUHIGHSCORE); } else if(set=="introhighscorefile") { tempName=val; } else if(set=="introhighscoresize") { genFontTex(tempName, atoi(val.data()), FONT_INTROHIGHSCORE); } else if(set=="introdescriptionfile") { tempName=val; } else if(set=="introdescriptionsize") { genFontTex(tempName, atoi(val.data()), FONT_INTRODESCRIPTION); } } } f.close(); } else { cout << "Error: could not open font-description file."; } TTF_Quit(); } void glTextClass::genFontTex(string TTFfontName, int fontSize, int font) { TTF_Font *ttfFont = NULL; SDL_Surface *c, *t; Uint32 rmask, gmask, bmask, amask; char tempChar[2] = { 0,0 }; int sX=0,sY=0; //Size of the rendered character SDL_Rect src={0,0,0,0},dst={0,0,0,0}; SDL_Color white = { 255,255,255 }; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif ttfFont = TTF_OpenFont( useTheme(TTFfontName,setting.gfxTheme).data(), fontSize ); t = SDL_CreateRGBSurface(0, 512, 512, 32, rmask,gmask,bmask,amask); dst.x=1; dst.y=1; fontInfo[font].height=0.0; for(int i=32; i < 128; i++) { tempChar[0] = (char)i; //Render to surface c = TTF_RenderText_Blended(ttfFont, tempChar, white); SDL_SetAlpha(c, 0, 0); TTF_SizeUTF8(ttfFont, tempChar, &sX, &sY); src.x=0; src.y=0; src.w=sX; src.h=sY; if(dst.x + sX > 512) { dst.x=1; dst.y += sY+2; if(dst.y > 512 && font != FONT_HIGHSCORE) //FONT_HIGHSCORE is always rendered too big for texture { cout << "Too many chars for tex ("< fontInfo[font].height) { fontInfo[font].height = sY/800.0; } //blit dst.w=sX; dst.h=sY; SDL_BlitSurface(c,&src,t,&dst); dst.x += sX+2; // Waste some space 1 px padding around each char SDL_FreeSurface(c); //Free character-surface } glGenTextures(1, &fontInfo[font].tex); //Generate a gltexture for this font glBindTexture(GL_TEXTURE_2D, fontInfo[font].tex); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, t->w, t->h, GL_RGBA, GL_UNSIGNED_BYTE, t->pixels); TTF_CloseFont(ttfFont); //Free the font SDL_FreeSurface(t); //Free text-surface } void glTextClass::write(string text, int font,bool center, GLfloat scale, GLfloat x, GLfloat y) { int c; GLfloat sX,sY,posX=0; //We need to find out half of the string width in order to center if(center) { for(unsigned int i=0; i < text.length(); i++) { c = (unsigned int)text[i]; sX = fontInfo[font].ch[c].width*scale; posX += sX; } posX *= -1; } posX += x; glEnable( GL_TEXTURE_2D ); glBindTexture(GL_TEXTURE_2D, fontInfo[font].tex); //Draw the quads for(unsigned int i=0; i < text.length(); i++) { c = (unsigned int)text[i]; sX = fontInfo[font].ch[c].width*scale; sY = fontInfo[font].height*scale; posX += sX; glBegin(GL_QUADS); glTexCoord2f( fontInfo[font].ch[c].Xa,fontInfo[font].ch[c].Ya ); glVertex3f(-sX+posX, sY+y,0); glTexCoord2f( fontInfo[font].ch[c].Xb,fontInfo[font].ch[c].Ya ); glVertex3f( sX+posX, sY+y,0); glTexCoord2f( fontInfo[font].ch[c].Xb,fontInfo[font].ch[c].Yb ); glVertex3f( sX+posX,-sY+y,0); glTexCoord2f( fontInfo[font].ch[c].Xa,fontInfo[font].ch[c].Yb ); glVertex3f(-sX+posX,-sY+y,0); glEnd( ); posX += sX; } }