/* font.cc Manage textured-font for drawing text Copyright (C) 2000 Mathias Broxvall Yannick Perret 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "general.h" #include "glHelp.h" #include "animated.h" #include "map.h" #include "game.h" #include "font.h" #include "image.h" using namespace std; // // // sorry, this code is a port from a C project, so it is not really // coherent with the rest of the code of trackballs. // // /* data for font image */ unsigned char *font_data=NULL; #define CHAR_W 32 #define CHAR_H 32 #define BCHAR_W 4 #define BCHAR_H 32 #define CHARS_W 512 #define CHARS_H 256 #define CHAR_WNB 16 #define CHAR_HNB 8 int char_corresp[256]= {'A','Q','B','C','D','E','F','G','H','I','J','K','L','M','N','O', 'U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j', 'o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3', '8','9',',',';',':','.','!','?','*','$','=','(',')','/','\\','§', '%','&','"','{','}','[',']','|','`','\'','_','^','@','°','£','¤', '\0','\0',256+'"',256+'C',256+'R','\0','\0',256+'<',256+'>','Å','Ä','Ö','å','ä','ö',' ', '\0',256+'?',256+'*',256+'O',256+'/',256+'o','P','R','S','T','k','l','m','n',256+'f',' ', '\0','4','5','6','7','-','+','<','>','#','~',256+'!','\0',256+'X',256+'V',256+'l', }; /* access table */ /* Index by ascii value + 128 (so we can handle 8 bit ascii (negative values!) correctly. */ int char_access[2048]={0}; /* the theoretical ratio screen_x/screen_y */ #define SCREEN_RATIO (640./480.) Font *current_fonts[8] = {NULL}; int nb_fonts = 0; // global list of text drawn TextLine textlines[MAX_TEXT_LINE]; int max_line_used = 0; #define BASE_TIME 0.2 static Real total_time = 0.; void Font::init() { int i; nb_fonts = 1; current_fonts[0] = new Font("font.png"); //current_fonts[1] = new Font("font2.png"); //current_fonts[2] = new Font("font3.png"); // initialize texts for(i=0; ifontName = strdup(fname); this->color[0] = 1.; this->color[1] = 1.; this->color[2] = 1.; this->color[3] = 1.; this->fontTex = loadTexture(this->fontName, this); } Font::~Font() { } int Font::figureFontInfo(void *pixels, int tx, int ty) { int i, j, jj, x, xs, k, y; if((tx != CHARS_W)||(ty != CHARS_H)) { fprintf(stderr, "Font image is not %dx%d. Aborted.\n", CHARS_W, CHARS_H); return 0; } if(pixels == NULL) { fprintf(stderr, "Font image not loaded.\n"); return 0; } /* create access table for chars */ /* Changed to handle 8bit ascii */ memset(char_access,0,2048); for(i=0;i<256;i++) { j=char_corresp[i]+128; if(j >= 0 && j < 2048) char_access[j]=i; } /* for(i=0; i<2048; i++) { for(j=0; j<512; j++) { if (char_corresp[j] == i) { char_access[i] = j; break; } } }*/ /* Compute the X extention for each letter (the last non-transparent pixel for each letter area (32x32) */ k = 0; /* For each char */ for(jj=0; jj=0; x--) { for(y=0; ychar_sizes[k] = 0.; } else if (xs == CHAR_W-1) { this->char_sizes[k] = 1.; } else { this->char_sizes[k] = (float)(xs+1)/CHAR_W; } k++; } } /* now correct special characters (in particular the SPACE) */ for(k=0; kchar_sizes[k] = .3; /* SPACE is empty but correspond */ /* to a real extention */ } } /* Treat special '"' and '°' to not move cursor forward */ /* this->char_sizes[5*CHAR_WNB+2]=0; this->char_sizes[4*CHAR_WNB+14]=0; */ } int Font::addText(int font, const char *text, int x, int y, float sx, float sy, double delay, double offset, double stab, double ampl, int fix) { if ((font < 0)||(font >= nb_fonts)) font = 0; return(current_fonts[font]->l_addText(text, x, y, sx, sy, delay, offset, stab, ampl, fix)); } // add a text to be drawn (returns the ID of the text) int Font::l_addText(const char *text, int x, int y, float sx, float sy, double delay, double offset, double stab, double ampl, int fix) { int i, j; double cur; if ((text == NULL)||(strlen(text) == 0)) return(-1); // looking for a free place for(i=0; i= max_line_used) max_line_used = i+1; return(1); } // remove really all texts void Font::destroyAllText() { int i; for(i=0; i textlines[tl].tmax) { tr = 0.; } else tr = ((textlines[tl].tmax-textlines[tl].time[i])/textlines[tl].tmax); if (tr < 0.) tr = 0.; // pulse if (textlines[tl].time_pulse > 0.) { if (textlines[tl].time_pulse < BASE_TIME) tp = 0.25*textlines[tl].time_pulse/BASE_TIME; else tp = 0.25; } tm = 1. + textlines[tl].amplitude * tr * sin(4.*3.14159*(tim)) + tp * sin(3.31*3.14159*(total_time+i*0.1)); draw_a_char(index, x, textlines[tl].y, textlines[tl].sizex*tm, textlines[tl].sizey*tm); } i += offset; x += (int)(2.*textlines[tl].sizex*char_sizes[index]); } } void Font::draw_highlight(int tl) { int index, offset; float w; if ((tl < 0)||(textlines[tl].text == NULL)) return; index = get_letter_index("#S ", &offset); glColor4f(1.,1.,1.,textlines[tl].time_pulse/BASE_TIME); w = (float)l_getTextWidth(textlines[tl].text, textlines[tl].sizex) + textlines[tl].sizex; draw_a_char(index, (int)(textlines[tl].x+w/2.-1.5*textlines[tl].sizex), textlines[tl].y, w/2., textlines[tl].sizey); } // returns the effective width of the text int Font::getTextWidth(int font, const char *text, float sx) { if ((font < 0)||(font >= nb_fonts)) font = 0; return(current_fonts[font]->l_getTextWidth(text, sx)); } // returns the effective width of the text int Font::l_getTextWidth(const char *text, float sx) { int i, l = 0, index, offset; if ((text == NULL)||(strlen(text) == 0)) return(0); for(i=0; i= nb_fonts)) font = 0; return(current_fonts[font]->l_addCenterText(text, x, y, sx, sy, delay, offset, stab, ampl, fix)); } // same than 'add_text' but 'x' is the X-center of the text to draw int Font::l_addCenterText(const char *text, int x, int y, float sx, float sy, double delay, double offset, double stab, double ampl, int fix) { int width; width = l_getTextWidth(text, sx); return(l_addText(text, x-width/2, y, sx, sy, delay, offset, stab, ampl, fix)); } int Font::addRightText(int font, const char *text, int x, int y, float sx, float sy, double delay, double offset, double stab, double ampl, int fix) { if ((font < 0)||(font >= nb_fonts)) font = 0; return(current_fonts[font]->l_addRightText(text, x, y, sx, sy, delay, offset, stab, ampl, fix)); } // same than 'add_text' but 'x' is the right-cborder of the text to draw int Font::l_addRightText(const char *text, int x, int y, float sx, float sy, double delay, double offset, double stab, double ampl, int fix) { int width; width = l_getTextWidth(text, sx); return(l_addText(text, x-width, y, sx, sy, delay, offset, stab, ampl, fix)); } // returns true if some text is still drawn (usefull to wait for all text // to be removed with animation int Font::isTextDrawn() { int i; for(i=0; i<=max_line_used; i++) { if (textlines[i].text != NULL) { return(1); } } return(0); } // returns the ID of the selected text (-1 if none) int Font::getSelectedText(int mx, int my) { int i; for(i=0; i<=max_line_used; i++) { if (textlines[i].text != NULL) { if ((mx >= textlines[i].x0)&&(mx <= textlines[i].x1)&& (my >= textlines[i].y0)&&(my <= textlines[i].y1)) return(i); } } return(-1); } void Font::draw() { int i; Enter2DMode(); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); for(i=0; i<=max_line_used; i++) { if (textlines[i].text != NULL) { bindTexture(textlines[i].font->fontName); glBegin(GL_QUADS); if (textlines[i].pulse) { textlines[i].font->draw_highlight(i); } glColor4fv(textlines[i].font->color); textlines[i].font->draw_a_text(i); glEnd(); } } Leave2DMode(); } void Font::tick(Real t) { int i, j, stable; // update local elapsed time total_time += t; for(i=0; i 0) stable = 0; } if (stable) destroyText(i); continue; } if (textlines[i].pulse) textlines[i].time_pulse += t; if ((textlines[i].time_pulse > 0.)&&(!textlines[i].pulse)) textlines[i].time_pulse -= t; if ((textlines[i].stable)&&(!textlines[i].pulse)) continue; stable = 1; for(j=0; j= nb_fonts)) font = 0; current_fonts[font]->l_setColor(r, g, b); } void Font::setColor(int font, float r, float g, float b, float a) { if ((font < 0)||(font >= nb_fonts)) font = 0; current_fonts[font]->l_setColor(r, g, b, a); } void Font::setTransp(int font, float a) { if ((font < 0)||(font >= nb_fonts)) font = 0; current_fonts[font]->l_setTransp(a); } void Font::resetColor(int font) { if ((font < 0)||(font >= nb_fonts)) font = 0; current_fonts[font]->l_resetColor(); } void Font::l_resetColor() { color[0] = 1.; color[1] = 1.; color[2] = 1.; color[3] = 1.; } void Font::l_setColor(float r, float g, float b) { color[0] = r; color[1] = g; color[2] = b; } void Font::l_setColor(float r, float g, float b, float a) { color[0] = r; color[1] = g; color[2] = b; color[3] = a; } void Font::l_setTransp(float a) { color[3] = a; } void Font::changeText(int tl, const char *text) { int i; if (tl < 0) return; if (textlines[tl].text == NULL) return; free(textlines[tl].text); free(textlines[tl].time); textlines[tl].text = strdup(text); textlines[tl].length = strlen(text); textlines[tl].time = (float*)malloc(sizeof(float)*strlen(text)); if (textlines[tl].time == NULL) { fprintf(stderr, "Cannot perform allocation in Font system. Text removed.\n"); if (textlines[tl].text != NULL) free(textlines[tl].text); textlines[tl].text = NULL; return; } for(i=0; i= nb_fonts)) font = 0; return(current_fonts[font]->l_drawSimpleText(text, x, y, sx, sy, r, g, b, a)); } int Font::drawRightSimpleText(int font, const char *text, int x, int y, float sx, float sy, float r, float g, float b, float a) { if ((font < 0)||(font >= nb_fonts)) font = 0; return(current_fonts[font]->l_drawRightSimpleText(text, x, y, sx, sy, r, g, b, a)); } int Font::drawCenterSimpleText(int font, const char *text, int x, int y, float sx, float sy, float r, float g, float b, float a) { if ((font < 0)||(font >= nb_fonts)) font = 0; return(current_fonts[font]->l_drawCenterSimpleText(text, x, y, sx, sy, r, g, b, a)); } int Font::l_drawSimpleText(const char *text, int x, int y, float sx, float sy, float r, float g, float b, float a) { int i, offset, index; double tm, tr, tim; float cx; if ((text == NULL)||(strlen(text) == 0)) return(0); Enter2DMode(); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); bindTexture(fontName); glColor4f(r, g, b, a); glBegin(GL_QUADS); cx = (float)x; for(i=0; i= nb_fonts)) font = 0; return(current_fonts[font]->l_drawSimpleText3D(text, sx, sy)); } int Font::l_drawSimpleText3D(const char *text, float sx, float sy) { int i, offset, index; double tm, tr, tim; float cx, y; if ((text == NULL)||(strlen(text) == 0)) return(0); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); bindTexture(fontName); glBegin(GL_QUADS); cx = 0.; y = 0.; for(i=0; i